mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2024-11-20 02:11:40 +01:00
Reformatting with new scalariform version for sbt 0.13.17
This commit is contained in:
parent
45fe16ab5f
commit
f8a13fa3ab
@ -188,7 +188,7 @@ sealed abstract class BloomFilter extends NetworkElement {
|
||||
val filter = accumFilter.insert(TransactionOutPoint(txId, UInt32(h._2)))
|
||||
loop(t, filter)
|
||||
case h :: t => loop(t, accumFilter)
|
||||
case Nil => accumFilter
|
||||
case Nil => accumFilter
|
||||
}
|
||||
val p2pkOrMultiSigScriptPubKeys: Seq[(ScriptPubKey, Int)] = scriptPubKeysWithIndex.filter {
|
||||
case (s, index) => s.isInstanceOf[P2PKScriptPubKey] ||
|
||||
@ -243,7 +243,7 @@ sealed abstract class BloomFilter extends NetworkElement {
|
||||
object BloomFilter extends Factory[BloomFilter] {
|
||||
|
||||
private case class BloomFilterImpl(filterSize: CompactSizeUInt, data: Seq[Byte], hashFuncs: UInt32,
|
||||
tweak: UInt32, flags: BloomFlag) extends BloomFilter
|
||||
tweak: UInt32, flags: BloomFlag) extends BloomFilter
|
||||
/** Max bloom filter size as per [[https://bitcoin.org/en/developer-reference#filterload]] */
|
||||
val maxSize = UInt32(36000)
|
||||
|
||||
|
@ -59,8 +59,7 @@ sealed abstract class TestNet3 extends BitcoinNetwork {
|
||||
override def rpcPort = 18332
|
||||
override def dnsSeeds = Seq(
|
||||
"testnet-seed.bitcoin.petertodd.org",
|
||||
"testnet-seed.bluematt.me", "testnet-seed.bitcoin.schildbach.de"
|
||||
)
|
||||
"testnet-seed.bluematt.me", "testnet-seed.bitcoin.schildbach.de")
|
||||
override def magicBytes = Seq(0x0b.toByte, 0x11.toByte, 0x09.toByte, 0x07.toByte)
|
||||
|
||||
override def difficultyChangeThreshold: Int = 2016
|
||||
|
@ -29,7 +29,7 @@ trait Merkle extends BitcoinSLogger {
|
||||
* @return the merkle root for the sequence of transactions
|
||||
*/
|
||||
def computeMerkleRoot(transactions: Seq[Transaction]): DoubleSha256Digest = transactions match {
|
||||
case Nil => throw new IllegalArgumentException("We cannot have zero transactions in the block. There always should be ATLEAST one - the coinbase tx")
|
||||
case Nil => throw new IllegalArgumentException("We cannot have zero transactions in the block. There always should be ATLEAST one - the coinbase tx")
|
||||
case h :: Nil => h.txId
|
||||
case h :: t =>
|
||||
val leafs = transactions.map(tx => Leaf(tx.txId))
|
||||
@ -84,7 +84,7 @@ trait Merkle extends BitcoinSLogger {
|
||||
val coinbaseWTxId = CryptoUtil.emptyDoubleSha256Hash
|
||||
val hashes = block.transactions.tail.map {
|
||||
case wtx: WitnessTransaction => wtx.wTxId
|
||||
case btx: BaseTransaction => btx.txId
|
||||
case btx: BaseTransaction => btx.txId
|
||||
}
|
||||
build(coinbaseWTxId +: hashes)
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ sealed abstract class DERSignatureUtil {
|
||||
*/
|
||||
def isValidSignatureEncoding(signature: ECDigitalSignature): Boolean = {
|
||||
signature match {
|
||||
case EmptyDigitalSignature => true
|
||||
case EmptyDigitalSignature => true
|
||||
case signature: ECDigitalSignature => isValidSignatureEncoding(signature.bytes)
|
||||
}
|
||||
}
|
||||
@ -226,7 +226,7 @@ sealed abstract class DERSignatureUtil {
|
||||
}
|
||||
result match {
|
||||
case Success(bool) => bool
|
||||
case Failure(_) => false
|
||||
case Failure(_) => false
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,8 +42,7 @@ sealed abstract class BaseECKey extends NetworkElement {
|
||||
private def oldSign(dataToSign: Seq[Byte], signingKey: BaseECKey): ECDigitalSignature = {
|
||||
val signer: ECDSASigner = new ECDSASigner(new HMacDSAKCalculator(new SHA256Digest()))
|
||||
val privKey: ECPrivateKeyParameters = new ECPrivateKeyParameters(
|
||||
new BigInteger(1, signingKey.bytes.toArray), CryptoParams.curve
|
||||
)
|
||||
new BigInteger(1, signingKey.bytes.toArray), CryptoParams.curve)
|
||||
signer.init(true, privKey)
|
||||
val components: Array[BigInteger] = signer.generateSignature(dataToSign.toArray)
|
||||
val (r, s) = (components(0), components(1))
|
||||
|
@ -75,7 +75,7 @@ object ExtKey extends Factory[ExtKey] {
|
||||
require(bytes.size == 78, "Not 78 bytes")
|
||||
val version: Try[ExtKeyVersion] = ExtKeyVersion(bytes.take(4)) match {
|
||||
case Some(v) => Success(v)
|
||||
case None => Failure(new IllegalArgumentException("Invalid version for ExtKey"))
|
||||
case None => Failure(new IllegalArgumentException("Invalid version for ExtKey"))
|
||||
}
|
||||
val depth = UInt8(bytes.slice(4, 5))
|
||||
val fp = bytes.slice(5, 9)
|
||||
@ -126,8 +126,8 @@ sealed abstract class ExtPrivateKey extends ExtKey {
|
||||
}
|
||||
|
||||
def extPublicKey: ExtPublicKey = version match {
|
||||
case MainNetPriv => ExtPublicKey(MainNetPub, depth, fingerprint, childNum, chainCode, key.publicKey)
|
||||
case TestNet3Priv => ExtPublicKey(TestNet3Pub, depth, fingerprint, childNum, chainCode, key.publicKey)
|
||||
case MainNetPriv => ExtPublicKey(MainNetPub, depth, fingerprint, childNum, chainCode, key.publicKey)
|
||||
case TestNet3Priv => ExtPublicKey(TestNet3Pub, depth, fingerprint, childNum, chainCode, key.publicKey)
|
||||
case MainNetPub | TestNet3Pub => throw new IllegalArgumentException("Cannot have pubkey version in ExtPrivateKey, got: " + version)
|
||||
}
|
||||
|
||||
@ -137,8 +137,8 @@ sealed abstract class ExtPrivateKey extends ExtKey {
|
||||
}
|
||||
object ExtPrivateKey extends Factory[ExtPrivateKey] {
|
||||
private case class ExtPrivateKeyImpl(version: ExtKeyVersion, depth: UInt8,
|
||||
fingerprint: Seq[Byte], childNum: UInt32,
|
||||
chainCode: ChainCode, key: ECPrivateKey) extends ExtPrivateKey {
|
||||
fingerprint: Seq[Byte], childNum: UInt32,
|
||||
chainCode: ChainCode, key: ECPrivateKey) extends ExtPrivateKey {
|
||||
require(fingerprint.size == 4, "Fingerprint must be 4 bytes in size, got: " + fingerprint)
|
||||
}
|
||||
|
||||
@ -147,13 +147,13 @@ object ExtPrivateKey extends Factory[ExtPrivateKey] {
|
||||
val base58 = Base58.encode(bytes ++ CryptoUtil.doubleSHA256(bytes).bytes.take(4))
|
||||
ExtKey.fromString(base58) match {
|
||||
case Success(priv: ExtPrivateKey) => priv
|
||||
case Success(_: ExtPublicKey) => throw new IllegalArgumentException("Cannot create ext public in ExtPrivateKey")
|
||||
case f: Failure[_] => throw f.exception
|
||||
case Success(_: ExtPublicKey) => throw new IllegalArgumentException("Cannot create ext public in ExtPrivateKey")
|
||||
case f: Failure[_] => throw f.exception
|
||||
}
|
||||
}
|
||||
def apply(version: ExtKeyVersion, depth: UInt8,
|
||||
fingerprint: Seq[Byte], child: UInt32,
|
||||
chainCode: ChainCode, privateKey: ECPrivateKey): ExtPrivateKey = {
|
||||
fingerprint: Seq[Byte], child: UInt32,
|
||||
chainCode: ChainCode, privateKey: ECPrivateKey): ExtPrivateKey = {
|
||||
ExtPrivateKeyImpl(version, depth, fingerprint, child, chainCode, privateKey)
|
||||
}
|
||||
|
||||
@ -164,7 +164,7 @@ object ExtPrivateKey extends Factory[ExtPrivateKey] {
|
||||
def apply(version: ExtKeyVersion, seedOpt: Option[Seq[Byte]] = None): ExtPrivateKey = {
|
||||
val seed = seedOpt match {
|
||||
case Some(bytes) => bytes
|
||||
case None => ECPrivateKey().bytes
|
||||
case None => ECPrivateKey().bytes
|
||||
}
|
||||
val i = CryptoUtil.hmac512("Bitcoin seed".map(_.toByte), seed)
|
||||
val (il, ir) = i.splitAt(32)
|
||||
@ -189,8 +189,7 @@ sealed abstract class ExtPublicKey extends ExtKey {
|
||||
val tweaked = NativeSecp256k1.pubKeyTweakAdd(
|
||||
key.bytes.toArray,
|
||||
hmac.toArray,
|
||||
priv.isCompressed
|
||||
)
|
||||
priv.isCompressed)
|
||||
val childPubKey = ECPublicKey(tweaked)
|
||||
val bi = BigInt(new BigInteger(1, priv.bytes.toArray))
|
||||
//we do not handle this case since it is impossible
|
||||
@ -206,11 +205,11 @@ sealed abstract class ExtPublicKey extends ExtKey {
|
||||
|
||||
object ExtPublicKey extends Factory[ExtPublicKey] {
|
||||
private case class ExtPublicKeyImpl(version: ExtKeyVersion, depth: UInt8,
|
||||
fingerprint: Seq[Byte], childNum: UInt32,
|
||||
chainCode: ChainCode, key: ECPublicKey) extends ExtPublicKey
|
||||
fingerprint: Seq[Byte], childNum: UInt32,
|
||||
chainCode: ChainCode, key: ECPublicKey) extends ExtPublicKey
|
||||
|
||||
def apply(version: ExtKeyVersion, depth: UInt8,
|
||||
fingerprint: Seq[Byte], child: UInt32, chainCode: ChainCode, publicKey: ECPublicKey): ExtPublicKey = {
|
||||
fingerprint: Seq[Byte], child: UInt32, chainCode: ChainCode, publicKey: ECPublicKey): ExtPublicKey = {
|
||||
ExtPublicKeyImpl(version, depth, fingerprint, child, chainCode, publicKey)
|
||||
}
|
||||
|
||||
@ -221,7 +220,7 @@ object ExtPublicKey extends Factory[ExtPublicKey] {
|
||||
case Success(_: ExtPrivateKey) =>
|
||||
throw new IllegalArgumentException("Cannot create ext privatkey in ExtPublicKey")
|
||||
case Success(pub: ExtPublicKey) => pub
|
||||
case f: Failure[_] => throw f.exception
|
||||
case f: Failure[_] => throw f.exception
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ trait TransactionSignatureChecker extends BitcoinSLogger {
|
||||
* @return a boolean indicating if the signature is valid or not
|
||||
*/
|
||||
def checkSignature(txSignatureComponent: TxSigComponent, script: Seq[ScriptToken],
|
||||
pubKey: ECPublicKey, signature: ECDigitalSignature, flags: Seq[ScriptFlag]): TransactionSignatureCheckerResult = {
|
||||
pubKey: ECPublicKey, signature: ECDigitalSignature, flags: Seq[ScriptFlag]): TransactionSignatureCheckerResult = {
|
||||
logger.debug("Signature: " + signature)
|
||||
val pubKeyEncodedCorrectly = BitcoinScriptUtil.isValidPubKeyEncoding(pubKey, flags)
|
||||
if (ScriptFlagUtil.requiresStrictDerEncoding(flags) && !DERSignatureUtil.isValidSignatureEncoding(signature)) {
|
||||
@ -57,8 +57,7 @@ trait TransactionSignatureChecker extends BitcoinSLogger {
|
||||
TransactionSignatureSerializer.hashForSignature(
|
||||
txSignatureComponent.transaction,
|
||||
txSignatureComponent.inputIndex,
|
||||
sigsRemovedScript, hashType
|
||||
)
|
||||
sigsRemovedScript, hashType)
|
||||
case w: WitnessTxSigComponent =>
|
||||
TransactionSignatureSerializer.hashForSignature(w.transaction, w.inputIndex, sigsRemovedScript, hashType,
|
||||
w.amount, w.sigVersion)
|
||||
@ -88,8 +87,8 @@ trait TransactionSignatureChecker extends BitcoinSLogger {
|
||||
*/
|
||||
@tailrec
|
||||
final def multiSignatureEvaluator(txSignatureComponent: TxSigComponent, script: Seq[ScriptToken],
|
||||
sigs: List[ECDigitalSignature], pubKeys: List[ECPublicKey], flags: Seq[ScriptFlag],
|
||||
requiredSigs: Long): TransactionSignatureCheckerResult = {
|
||||
sigs: List[ECDigitalSignature], pubKeys: List[ECPublicKey], flags: Seq[ScriptFlag],
|
||||
requiredSigs: Long): TransactionSignatureCheckerResult = {
|
||||
logger.debug("Signatures inside of helper: " + sigs)
|
||||
logger.debug("Public keys inside of helper: " + pubKeys)
|
||||
if (sigs.size > pubKeys.size) {
|
||||
|
@ -44,7 +44,7 @@ sealed abstract class TransactionSignatureCreator {
|
||||
|
||||
/** This is the same as createSig above, except the 'sign' function returns a Future[ECDigitalSignature] */
|
||||
def createSig(component: TxSigComponent, sign: Seq[Byte] => Future[ECDigitalSignature],
|
||||
hashType: HashType)(implicit ec: ExecutionContext): Future[ECDigitalSignature] = {
|
||||
hashType: HashType)(implicit ec: ExecutionContext): Future[ECDigitalSignature] = {
|
||||
val hash = TransactionSignatureSerializer.hashForSignature(component, hashType)
|
||||
val signature = sign(hash.bytes)
|
||||
//append 1 byte hash type onto the end
|
||||
|
@ -139,7 +139,7 @@ sealed abstract class TransactionSignatureSerializer {
|
||||
* @return
|
||||
*/
|
||||
def hashForSignature(spendingTransaction: Transaction, inputIndex: UInt32, script: Seq[ScriptToken],
|
||||
hashType: HashType): DoubleSha256Digest = {
|
||||
hashType: HashType): DoubleSha256Digest = {
|
||||
//these first two checks are in accordance with behavior in bitcoin core
|
||||
//[[https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L1112-L1123]]
|
||||
if (inputIndex >= UInt32(spendingTransaction.inputs.size)) {
|
||||
@ -163,7 +163,7 @@ sealed abstract class TransactionSignatureSerializer {
|
||||
* [[https://github.com/bitcoin/bitcoin/blob/f8528134fc188abc5c7175a19680206964a8fade/src/script/interpreter.cpp#L1113]]
|
||||
*/
|
||||
def serializeForSignature(spendingTx: Transaction, inputIndex: UInt32, script: Seq[ScriptToken], hashType: HashType,
|
||||
amount: CurrencyUnit, signatureVersion: SignatureVersion): Seq[Byte] = signatureVersion match {
|
||||
amount: CurrencyUnit, signatureVersion: SignatureVersion): Seq[Byte] = signatureVersion match {
|
||||
case SigVersionBase =>
|
||||
serializeForSignature(spendingTx, inputIndex, script, hashType)
|
||||
case SigVersionWitnessV0 =>
|
||||
@ -209,7 +209,7 @@ sealed abstract class TransactionSignatureSerializer {
|
||||
* NOTE: This covers the amount of [[CurrencyUnit]] we are spending in the output
|
||||
*/
|
||||
def hashForSignature(spendingTx: Transaction, inputIndex: UInt32, script: Seq[ScriptToken], hashType: HashType,
|
||||
amount: CurrencyUnit, sigVersion: SignatureVersion): DoubleSha256Digest = {
|
||||
amount: CurrencyUnit, sigVersion: SignatureVersion): DoubleSha256Digest = {
|
||||
|
||||
val serialization = serializeForSignature(spendingTx, inputIndex, script, hashType, amount, sigVersion)
|
||||
CryptoUtil.doubleSHA256(serialization)
|
||||
|
@ -91,7 +91,7 @@ sealed abstract class WitnessTxSigComponentP2SH extends WitnessTxSigComponent {
|
||||
}
|
||||
|
||||
override def witnessVersion: WitnessVersion = witnessScriptPubKey match {
|
||||
case Success(w) => w.witnessVersion
|
||||
case Success(w) => w.witnessVersion
|
||||
case Failure(err) => throw err
|
||||
}
|
||||
|
||||
@ -119,10 +119,10 @@ sealed abstract class WitnessTxSigComponentRebuilt extends TxSigComponent {
|
||||
object BaseTxSigComponent {
|
||||
|
||||
private case class BaseTxSigComponentImpl(transaction: Transaction, inputIndex: UInt32,
|
||||
scriptPubKey: ScriptPubKey, flags: Seq[ScriptFlag]) extends BaseTxSigComponent
|
||||
scriptPubKey: ScriptPubKey, flags: Seq[ScriptFlag]) extends BaseTxSigComponent
|
||||
|
||||
def apply(transaction: Transaction, inputIndex: UInt32,
|
||||
scriptPubKey: ScriptPubKey, flags: Seq[ScriptFlag]): BaseTxSigComponent = {
|
||||
scriptPubKey: ScriptPubKey, flags: Seq[ScriptFlag]): BaseTxSigComponent = {
|
||||
BaseTxSigComponentImpl(transaction, inputIndex, scriptPubKey, flags)
|
||||
}
|
||||
|
||||
@ -131,12 +131,12 @@ object BaseTxSigComponent {
|
||||
object WitnessTxSigComponent {
|
||||
|
||||
def apply(transaction: WitnessTransaction, inputIndex: UInt32, scriptPubKey: WitnessScriptPubKey,
|
||||
flags: Seq[ScriptFlag], amount: CurrencyUnit): WitnessTxSigComponent = {
|
||||
flags: Seq[ScriptFlag], amount: CurrencyUnit): WitnessTxSigComponent = {
|
||||
WitnessTxSigComponentRaw(transaction, inputIndex, scriptPubKey, flags, amount)
|
||||
}
|
||||
|
||||
def apply(transaction: WitnessTransaction, inputIndex: UInt32, scriptPubKey: P2SHScriptPubKey,
|
||||
flags: Seq[ScriptFlag], amount: CurrencyUnit): WitnessTxSigComponent = {
|
||||
flags: Seq[ScriptFlag], amount: CurrencyUnit): WitnessTxSigComponent = {
|
||||
WitnessTxSigComponentP2SH(transaction, inputIndex, scriptPubKey, flags, amount)
|
||||
}
|
||||
|
||||
@ -145,11 +145,11 @@ object WitnessTxSigComponent {
|
||||
object WitnessTxSigComponentRaw {
|
||||
|
||||
private case class WitnessTxSigComponentRawImpl(transaction: WitnessTransaction, inputIndex: UInt32,
|
||||
scriptPubKey: WitnessScriptPubKey, flags: Seq[ScriptFlag],
|
||||
amount: CurrencyUnit) extends WitnessTxSigComponentRaw
|
||||
scriptPubKey: WitnessScriptPubKey, flags: Seq[ScriptFlag],
|
||||
amount: CurrencyUnit) extends WitnessTxSigComponentRaw
|
||||
|
||||
def apply(transaction: WitnessTransaction, inputIndex: UInt32,
|
||||
scriptPubKey: WitnessScriptPubKey, flags: Seq[ScriptFlag], amount: CurrencyUnit): WitnessTxSigComponentRaw = {
|
||||
scriptPubKey: WitnessScriptPubKey, flags: Seq[ScriptFlag], amount: CurrencyUnit): WitnessTxSigComponentRaw = {
|
||||
WitnessTxSigComponentRawImpl(transaction, inputIndex, scriptPubKey, flags, amount)
|
||||
}
|
||||
}
|
||||
@ -157,11 +157,11 @@ object WitnessTxSigComponentRaw {
|
||||
object WitnessTxSigComponentP2SH {
|
||||
|
||||
private case class WitnessTxSigComponentP2SHImpl(transaction: WitnessTransaction, inputIndex: UInt32,
|
||||
scriptPubKey: P2SHScriptPubKey, flags: Seq[ScriptFlag],
|
||||
amount: CurrencyUnit) extends WitnessTxSigComponentP2SH
|
||||
scriptPubKey: P2SHScriptPubKey, flags: Seq[ScriptFlag],
|
||||
amount: CurrencyUnit) extends WitnessTxSigComponentP2SH
|
||||
|
||||
def apply(transaction: WitnessTransaction, inputIndex: UInt32, scriptPubKey: P2SHScriptPubKey, flags: Seq[ScriptFlag],
|
||||
amount: CurrencyUnit): WitnessTxSigComponentP2SH = {
|
||||
amount: CurrencyUnit): WitnessTxSigComponentP2SH = {
|
||||
|
||||
WitnessTxSigComponentP2SHImpl(transaction, inputIndex, scriptPubKey, flags, amount)
|
||||
}
|
||||
@ -170,11 +170,11 @@ object WitnessTxSigComponentP2SH {
|
||||
object WitnessTxSigComponentRebuilt {
|
||||
|
||||
private case class WitnessTxSigComponentRebuiltImpl(transaction: WitnessTransaction, inputIndex: UInt32,
|
||||
scriptPubKey: ScriptPubKey, witnessScriptPubKey: WitnessScriptPubKey,
|
||||
flags: Seq[ScriptFlag], amount: CurrencyUnit) extends WitnessTxSigComponentRebuilt
|
||||
scriptPubKey: ScriptPubKey, witnessScriptPubKey: WitnessScriptPubKey,
|
||||
flags: Seq[ScriptFlag], amount: CurrencyUnit) extends WitnessTxSigComponentRebuilt
|
||||
|
||||
def apply(wtx: WitnessTransaction, inputIndex: UInt32, scriptPubKey: ScriptPubKey, witScriptPubKey: WitnessScriptPubKey,
|
||||
flags: Seq[ScriptFlag], amount: CurrencyUnit): WitnessTxSigComponentRebuilt = {
|
||||
flags: Seq[ScriptFlag], amount: CurrencyUnit): WitnessTxSigComponentRebuilt = {
|
||||
WitnessTxSigComponentRebuiltImpl(wtx, inputIndex, scriptPubKey, witScriptPubKey, flags, amount)
|
||||
}
|
||||
}
|
@ -99,14 +99,13 @@ object Bech32Address {
|
||||
private val logger = BitcoinSLogger.logger
|
||||
|
||||
def apply(
|
||||
witSPK: WitnessScriptPubKey,
|
||||
networkParameters: NetworkParameters
|
||||
): Try[Bech32Address] = {
|
||||
witSPK: WitnessScriptPubKey,
|
||||
networkParameters: NetworkParameters): Try[Bech32Address] = {
|
||||
//we don't encode the wit version or pushop for program into base5
|
||||
val prog = UInt8.toUInt8s(witSPK.asmBytes.tail.tail)
|
||||
val encoded = Bech32Address.encode(prog)
|
||||
val hrp = networkParameters match {
|
||||
case _: MainNet => bc
|
||||
case _: MainNet => bc
|
||||
case _: TestNet3 | _: RegTest => tb
|
||||
}
|
||||
val witVersion = witSPK.witnessVersion.version.toLong.toShort
|
||||
@ -148,8 +147,7 @@ object Bech32Address {
|
||||
private def generators: Seq[Long] = Seq(
|
||||
UInt32("3b6a57b2").toLong,
|
||||
UInt32("26508e6d").toLong, UInt32("1ea119fa").toLong,
|
||||
UInt32("3d4233dd").toLong, UInt32("2a1462b3").toLong
|
||||
)
|
||||
UInt32("3d4233dd").toLong, UInt32("2a1462b3").toLong)
|
||||
|
||||
def polyMod(bytes: Seq[UInt8]): Long = {
|
||||
var chk: Long = 1
|
||||
@ -203,7 +201,7 @@ object Bech32Address {
|
||||
case Some(v) =>
|
||||
WitnessScriptPubKey(Seq(v.version) ++ pushOp ++ Seq(ScriptConstant(prog))) match {
|
||||
case Some(spk) => Success(spk)
|
||||
case None => Failure(new IllegalArgumentException("Failed to decode bech32 into a witSPK"))
|
||||
case None => Failure(new IllegalArgumentException("Failed to decode bech32 into a witSPK"))
|
||||
}
|
||||
case None => Failure(new IllegalArgumentException("Witness version was not valid, got: " + v))
|
||||
}
|
||||
@ -304,9 +302,8 @@ object Bech32Address {
|
||||
|
||||
object P2PKHAddress {
|
||||
private case class P2PKHAddressImpl(
|
||||
hash: Sha256Hash160Digest,
|
||||
networkParameters: NetworkParameters
|
||||
) extends P2PKHAddress {
|
||||
hash: Sha256Hash160Digest,
|
||||
networkParameters: NetworkParameters) extends P2PKHAddress {
|
||||
require(isP2PKHAddress(value), "Bitcoin address was invalid " + value)
|
||||
}
|
||||
|
||||
@ -338,9 +335,8 @@ object P2PKHAddress {
|
||||
|
||||
object P2SHAddress {
|
||||
private case class P2SHAddressImpl(
|
||||
hash: Sha256Hash160Digest,
|
||||
networkParameters: NetworkParameters
|
||||
) extends P2SHAddress {
|
||||
hash: Sha256Hash160Digest,
|
||||
networkParameters: NetworkParameters) extends P2SHAddress {
|
||||
require(isP2SHAddress(value), "Bitcoin address was invalid " + value)
|
||||
}
|
||||
|
||||
@ -427,8 +423,8 @@ object Address {
|
||||
def apply(str: String): Try[Address] = Try(BitcoinAddress(str))
|
||||
|
||||
def fromScriptPubKey(spk: ScriptPubKey, network: NetworkParameters): Try[BitcoinAddress] = spk match {
|
||||
case p2pkh: P2PKHScriptPubKey => Success(P2PKHAddress(p2pkh, network))
|
||||
case p2sh: P2SHScriptPubKey => Success(P2SHAddress(p2sh, network))
|
||||
case p2pkh: P2PKHScriptPubKey => Success(P2PKHAddress(p2pkh, network))
|
||||
case p2sh: P2SHScriptPubKey => Success(P2SHAddress(p2sh, network))
|
||||
case witSPK: WitnessScriptPubKey => Bech32Address(witSPK, network)
|
||||
case x @ (_: P2PKScriptPubKey | _: MultiSignatureScriptPubKey | _: LockTimeScriptPubKey
|
||||
| _: EscrowTimeoutScriptPubKey | _: NonStandardScriptPubKey
|
||||
|
@ -52,8 +52,7 @@ object Block extends Factory[Block] {
|
||||
|
||||
private sealed case class BlockImpl(
|
||||
blockHeader: BlockHeader,
|
||||
txCount: CompactSizeUInt, transactions: Seq[Transaction]
|
||||
) extends Block
|
||||
txCount: CompactSizeUInt, transactions: Seq[Transaction]) extends Block
|
||||
|
||||
def apply(blockHeader: BlockHeader, txCount: CompactSizeUInt, transactions: Seq[Transaction]): Block = {
|
||||
BlockImpl(blockHeader, txCount, transactions)
|
||||
|
@ -91,10 +91,10 @@ sealed trait BlockHeader extends NetworkElement {
|
||||
object BlockHeader extends Factory[BlockHeader] {
|
||||
|
||||
private sealed case class BlockHeaderImpl(version: UInt32, previousBlockHash: DoubleSha256Digest,
|
||||
merkleRootHash: DoubleSha256Digest, time: UInt32, nBits: UInt32, nonce: UInt32) extends BlockHeader
|
||||
merkleRootHash: DoubleSha256Digest, time: UInt32, nBits: UInt32, nonce: UInt32) extends BlockHeader
|
||||
|
||||
def apply(version: UInt32, previousBlockHash: DoubleSha256Digest, merkleRootHash: DoubleSha256Digest,
|
||||
time: UInt32, nBits: UInt32, nonce: UInt32): BlockHeader = {
|
||||
time: UInt32, nBits: UInt32, nonce: UInt32): BlockHeader = {
|
||||
BlockHeaderImpl(version, previousBlockHash, merkleRootHash, time, nBits, nonce)
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ sealed abstract class ChainParams {
|
||||
* @return the newly minted genesis block
|
||||
*/
|
||||
def createGenesisBlock(timestamp: String, scriptPubKey: ScriptPubKey, time: UInt32, nonce: UInt32, nBits: UInt32,
|
||||
version: UInt32, amount: CurrencyUnit): Block = {
|
||||
version: UInt32, amount: CurrencyUnit): Block = {
|
||||
val timestampBytes = timestamp.getBytes(StandardCharsets.UTF_8)
|
||||
//see https://bitcoin.stackexchange.com/questions/13122/scriptsig-coinbase-structure-of-the-genesis-block
|
||||
//for a full breakdown of the genesis block & its script signature
|
||||
@ -108,8 +108,7 @@ object MainNetChainParams extends BitcoinChainParams {
|
||||
Base58Type.ExtPublicKey -> Seq(BitcoinSUtil.hexToByte("04"), BitcoinSUtil.hexToByte("88"),
|
||||
BitcoinSUtil.hexToByte("b2"), BitcoinSUtil.hexToByte("1e")),
|
||||
Base58Type.ExtSecretKey -> Seq(BitcoinSUtil.hexToByte("04"), BitcoinSUtil.hexToByte("88"),
|
||||
BitcoinSUtil.hexToByte("ad"), BitcoinSUtil.hexToByte("e4"))
|
||||
)
|
||||
BitcoinSUtil.hexToByte("ad"), BitcoinSUtil.hexToByte("e4")))
|
||||
}
|
||||
|
||||
object TestNetChainParams extends BitcoinChainParams {
|
||||
@ -125,8 +124,7 @@ object TestNetChainParams extends BitcoinChainParams {
|
||||
Base58Type.ExtPublicKey -> Seq(BitcoinSUtil.hexToByte("04"), BitcoinSUtil.hexToByte("35"),
|
||||
BitcoinSUtil.hexToByte("87"), BitcoinSUtil.hexToByte("cf")),
|
||||
Base58Type.ExtSecretKey -> Seq(BitcoinSUtil.hexToByte("04"), BitcoinSUtil.hexToByte("35"),
|
||||
BitcoinSUtil.hexToByte("83"), BitcoinSUtil.hexToByte("94"))
|
||||
)
|
||||
BitcoinSUtil.hexToByte("83"), BitcoinSUtil.hexToByte("94")))
|
||||
}
|
||||
|
||||
object RegTestNetChainParams extends BitcoinChainParams {
|
||||
|
@ -36,7 +36,7 @@ sealed abstract class MerkleBlock extends NetworkElement {
|
||||
object MerkleBlock extends Factory[MerkleBlock] {
|
||||
|
||||
private case class MerkleBlockImpl(blockHeader: BlockHeader, transactionCount: UInt32,
|
||||
partialMerkleTree: PartialMerkleTree) extends MerkleBlock
|
||||
partialMerkleTree: PartialMerkleTree) extends MerkleBlock
|
||||
/**
|
||||
* Creates a [[MerkleBlock]] from the given [[Block]] and [[BloomFilter]]
|
||||
* This function iterates through each transaction inside our block checking if it is relevant to the given bloom filter
|
||||
@ -48,7 +48,7 @@ object MerkleBlock extends Factory[MerkleBlock] {
|
||||
def apply(block: Block, filter: BloomFilter): (MerkleBlock, BloomFilter) = {
|
||||
@tailrec
|
||||
def loop(remainingTxs: Seq[Transaction], accumFilter: BloomFilter,
|
||||
txMatches: Seq[(Boolean, DoubleSha256Digest)]): (Seq[(Boolean, DoubleSha256Digest)], BloomFilter) = {
|
||||
txMatches: Seq[(Boolean, DoubleSha256Digest)]): (Seq[(Boolean, DoubleSha256Digest)], BloomFilter) = {
|
||||
if (remainingTxs.isEmpty) (txMatches.reverse, accumFilter)
|
||||
else {
|
||||
val tx = remainingTxs.head
|
||||
@ -85,7 +85,7 @@ object MerkleBlock extends Factory[MerkleBlock] {
|
||||
}
|
||||
|
||||
def apply(blockHeader: BlockHeader, txCount: UInt32,
|
||||
partialMerkleTree: PartialMerkleTree): MerkleBlock = {
|
||||
partialMerkleTree: PartialMerkleTree): MerkleBlock = {
|
||||
MerkleBlockImpl(blockHeader, txCount, partialMerkleTree)
|
||||
}
|
||||
|
||||
|
@ -57,9 +57,8 @@ sealed trait PartialMerkleTree extends BitcoinSLogger {
|
||||
logger.debug("Starting bits for extraction: " + bits)
|
||||
logger.debug("Starting tree: " + tree)
|
||||
def loop(
|
||||
subTree: BinaryTree[DoubleSha256Digest],
|
||||
remainingBits: Seq[Boolean], height: Int, pos: Int, accumMatches: Seq[DoubleSha256Digest]
|
||||
): (Seq[DoubleSha256Digest], Seq[Boolean]) = {
|
||||
subTree: BinaryTree[DoubleSha256Digest],
|
||||
remainingBits: Seq[Boolean], height: Int, pos: Int, accumMatches: Seq[DoubleSha256Digest]): (Seq[DoubleSha256Digest], Seq[Boolean]) = {
|
||||
if (height == maxHeight) extractLeafMatch(accumMatches, remainingBits, subTree)
|
||||
else {
|
||||
//means we have a nontxid node
|
||||
@ -90,7 +89,7 @@ sealed trait PartialMerkleTree extends BitcoinSLogger {
|
||||
|
||||
/** Handles a leaf match when we are extracting matches from the partial merkle tree */
|
||||
private def extractLeafMatch(accumMatches: Seq[DoubleSha256Digest], remainingBits: Seq[Boolean],
|
||||
subTree: BinaryTree[DoubleSha256Digest]): (Seq[DoubleSha256Digest], Seq[Boolean]) = {
|
||||
subTree: BinaryTree[DoubleSha256Digest]): (Seq[DoubleSha256Digest], Seq[Boolean]) = {
|
||||
if (remainingBits.head) {
|
||||
//means we have a txid node that matched the filter
|
||||
subTree match {
|
||||
@ -111,7 +110,7 @@ object PartialMerkleTree {
|
||||
private val logger = BitcoinSLogger.logger
|
||||
|
||||
private case class PartialMerkleTreeImpl(tree: BinaryTree[DoubleSha256Digest], transactionCount: UInt32,
|
||||
bits: Seq[Boolean], hashes: Seq[DoubleSha256Digest]) extends PartialMerkleTree
|
||||
bits: Seq[Boolean], hashes: Seq[DoubleSha256Digest]) extends PartialMerkleTree
|
||||
|
||||
def apply(txMatches: Seq[(Boolean, DoubleSha256Digest)]): PartialMerkleTree = {
|
||||
val txIds = txMatches.map(_._2)
|
||||
@ -241,8 +240,7 @@ object PartialMerkleTree {
|
||||
(
|
||||
Leaf(remainingHashes.head),
|
||||
remainingHashes.tail,
|
||||
remainingMatches.tail
|
||||
)
|
||||
remainingMatches.tail)
|
||||
} else {
|
||||
//means we have a non txid node
|
||||
if (remainingMatches.head) {
|
||||
|
@ -12,7 +12,7 @@ trait ScriptFactory[T] extends Factory[T] {
|
||||
|
||||
/** Builds a script from the given asm with the given constructor if the invariant holds true, else throws an error */
|
||||
def buildScript(asm: Seq[ScriptToken], constructor: Seq[Byte] => T,
|
||||
invariant: Seq[ScriptToken] => Boolean, errorMsg: String): T = {
|
||||
invariant: Seq[ScriptToken] => Boolean, errorMsg: String): T = {
|
||||
if (invariant(asm)) {
|
||||
val asmBytes = asm.flatMap(_.bytes)
|
||||
val compactSizeUInt = CompactSizeUInt.calc(asmBytes)
|
||||
|
@ -296,7 +296,7 @@ sealed trait LockTimeScriptPubKey extends ScriptPubKey {
|
||||
def nestedScriptPubKey: ScriptPubKey = {
|
||||
val bool: Boolean = asm.head.isInstanceOf[ScriptNumberOperation]
|
||||
bool match {
|
||||
case true => ScriptPubKey(asm.slice(3, asm.length))
|
||||
case true => ScriptPubKey(asm.slice(3, asm.length))
|
||||
case false => ScriptPubKey(asm.slice(4, asm.length))
|
||||
}
|
||||
}
|
||||
@ -305,7 +305,7 @@ sealed trait LockTimeScriptPubKey extends ScriptPubKey {
|
||||
def locktime: ScriptNumber = {
|
||||
asm.head match {
|
||||
case scriptNumOp: ScriptNumberOperation => ScriptNumber(scriptNumOp.toLong)
|
||||
case _: BytesToPushOntoStack => ScriptNumber(asm(1).hex)
|
||||
case _: BytesToPushOntoStack => ScriptNumber(asm(1).hex)
|
||||
case x @ (_: ScriptConstant | _: ScriptOperation) => throw new IllegalArgumentException("In a LockTimeScriptPubKey, " +
|
||||
"the first asm must be either a ScriptNumberOperation (i.e. OP_5), or the BytesToPushOntoStack for the proceeding ScriptConstant.")
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ sealed trait P2SHScriptSignature extends ScriptSignature {
|
||||
val asmWithoutRedeemScriptAndPushOp: Try[Seq[ScriptToken]] = Try {
|
||||
asm(asm.size - 2) match {
|
||||
case b: BytesToPushOntoStack => asm.dropRight(2)
|
||||
case _ => asm.dropRight(3)
|
||||
case _ => asm.dropRight(3)
|
||||
}
|
||||
}
|
||||
val script = asmWithoutRedeemScriptAndPushOp.getOrElse(EmptyScriptSignature.asm)
|
||||
@ -209,7 +209,7 @@ object P2SHScriptSignature extends ScriptFactory[P2SHScriptSignature] {
|
||||
| _: WitnessScriptPubKeyV0 | _: UnassignedWitnessScriptPubKey
|
||||
| _: EscrowTimeoutScriptPubKey => true
|
||||
case _: NonStandardScriptPubKey | _: WitnessCommitment => false
|
||||
case EmptyScriptPubKey => false
|
||||
case EmptyScriptPubKey => false
|
||||
}
|
||||
case Failure(_) => false
|
||||
}
|
||||
@ -274,8 +274,7 @@ object MultiSignatureScriptSignature extends ScriptFactory[MultiSignatureScriptS
|
||||
case false =>
|
||||
val firstTokenIsScriptNumberOperation = asm.head.isInstanceOf[ScriptNumberOperation]
|
||||
val restOfScriptIsPushOpsOrScriptConstants = asm.tail.map(
|
||||
token => token.isInstanceOf[ScriptConstant] || StackPushOperationFactory.isPushOperation(token)
|
||||
).exists(_ == false)
|
||||
token => token.isInstanceOf[ScriptConstant] || StackPushOperationFactory.isPushOperation(token)).exists(_ == false)
|
||||
firstTokenIsScriptNumberOperation && !restOfScriptIsPushOpsOrScriptConstants
|
||||
}
|
||||
}
|
||||
@ -401,13 +400,13 @@ object ScriptSignature extends Factory[ScriptSignature] {
|
||||
* @return
|
||||
*/
|
||||
def fromScriptPubKey(tokens: Seq[ScriptToken], scriptPubKey: ScriptPubKey): Try[ScriptSignature] = scriptPubKey match {
|
||||
case _: P2SHScriptPubKey => Try(P2SHScriptSignature.fromAsm(tokens))
|
||||
case _: P2PKHScriptPubKey => Try(P2PKHScriptSignature.fromAsm(tokens))
|
||||
case _: P2PKScriptPubKey => Try(P2PKScriptSignature.fromAsm(tokens))
|
||||
case _: P2SHScriptPubKey => Try(P2SHScriptSignature.fromAsm(tokens))
|
||||
case _: P2PKHScriptPubKey => Try(P2PKHScriptSignature.fromAsm(tokens))
|
||||
case _: P2PKScriptPubKey => Try(P2PKScriptSignature.fromAsm(tokens))
|
||||
case _: MultiSignatureScriptPubKey => Try(MultiSignatureScriptSignature.fromAsm(tokens))
|
||||
case _: NonStandardScriptPubKey => Try(NonStandardScriptSignature.fromAsm(tokens))
|
||||
case s: CLTVScriptPubKey => fromScriptPubKey(tokens, s.nestedScriptPubKey)
|
||||
case s: CSVScriptPubKey => fromScriptPubKey(tokens, s.nestedScriptPubKey)
|
||||
case _: NonStandardScriptPubKey => Try(NonStandardScriptSignature.fromAsm(tokens))
|
||||
case s: CLTVScriptPubKey => fromScriptPubKey(tokens, s.nestedScriptPubKey)
|
||||
case s: CSVScriptPubKey => fromScriptPubKey(tokens, s.nestedScriptPubKey)
|
||||
case escrowWithTimeout: EscrowTimeoutScriptPubKey =>
|
||||
val isMultiSig = BitcoinScriptUtil.castToBool(tokens.last)
|
||||
if (isMultiSig) {
|
||||
@ -498,7 +497,7 @@ object EscrowTimeoutScriptSignature extends Factory[EscrowTimeoutScriptSignature
|
||||
|
||||
def apply(scriptSig: ScriptSignature): Try[EscrowTimeoutScriptSignature] = scriptSig match {
|
||||
case m: MultiSignatureScriptSignature => Success(fromMultiSig(m))
|
||||
case lock: LockTimeScriptSignature => Success(fromLockTime(lock))
|
||||
case lock: LockTimeScriptSignature => Success(fromLockTime(lock))
|
||||
case x @ (_: P2PKScriptSignature | _: P2PKHScriptSignature | _: P2SHScriptSignature | _: NonStandardScriptSignature
|
||||
| _: EscrowTimeoutScriptSignature | EmptyScriptSignature) => Failure(new IllegalArgumentException("Cannot create a EscrowTimeoutScriptSignature out of " + x))
|
||||
|
||||
|
@ -36,7 +36,7 @@ sealed abstract class P2WPKHWitnessV0 extends ScriptWitness {
|
||||
def pubKey: ECPublicKey = ECPublicKey(stack.head)
|
||||
|
||||
def signature: ECDigitalSignature = stack(1) match {
|
||||
case Nil => EmptyDigitalSignature
|
||||
case Nil => EmptyDigitalSignature
|
||||
case bytes: Seq[Byte] => ECDigitalSignature(bytes)
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ sealed abstract class Transaction extends NetworkElement {
|
||||
* [[https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#Transaction_size_calculations]]
|
||||
*/
|
||||
def baseSize: Long = this match {
|
||||
case btx: BaseTransaction => btx.size
|
||||
case btx: BaseTransaction => btx.size
|
||||
case wtx: WitnessTransaction => BaseTransaction(wtx.version, wtx.inputs, wtx.outputs, wtx.lockTime).baseSize
|
||||
}
|
||||
|
||||
@ -62,7 +62,7 @@ sealed abstract class Transaction extends NetworkElement {
|
||||
def isCoinbase: Boolean = inputs.size match {
|
||||
case 1 => inputs.head match {
|
||||
case coinbase: CoinbaseInput => true
|
||||
case _: TransactionInput => false
|
||||
case _: TransactionInput => false
|
||||
}
|
||||
case _: Int => false
|
||||
}
|
||||
@ -129,21 +129,21 @@ object Transaction extends Factory[Transaction] {
|
||||
|
||||
object BaseTransaction extends Factory[BaseTransaction] {
|
||||
private case class BaseTransactionImpl(version: UInt32, inputs: Seq[TransactionInput],
|
||||
outputs: Seq[TransactionOutput], lockTime: UInt32) extends BaseTransaction
|
||||
outputs: Seq[TransactionOutput], lockTime: UInt32) extends BaseTransaction
|
||||
|
||||
override def fromBytes(bytes: Seq[Byte]): BaseTransaction = RawBaseTransactionParser.read(bytes)
|
||||
|
||||
def apply(version: UInt32, inputs: Seq[TransactionInput],
|
||||
outputs: Seq[TransactionOutput], lockTime: UInt32): BaseTransaction = BaseTransactionImpl(version, inputs, outputs, lockTime)
|
||||
outputs: Seq[TransactionOutput], lockTime: UInt32): BaseTransaction = BaseTransactionImpl(version, inputs, outputs, lockTime)
|
||||
}
|
||||
|
||||
object WitnessTransaction extends Factory[WitnessTransaction] {
|
||||
private case class WitnessTransactionImpl(version: UInt32, inputs: Seq[TransactionInput],
|
||||
outputs: Seq[TransactionOutput], lockTime: UInt32,
|
||||
witness: TransactionWitness) extends WitnessTransaction
|
||||
outputs: Seq[TransactionOutput], lockTime: UInt32,
|
||||
witness: TransactionWitness) extends WitnessTransaction
|
||||
|
||||
def apply(version: UInt32, inputs: Seq[TransactionInput], outputs: Seq[TransactionOutput],
|
||||
lockTime: UInt32, witness: TransactionWitness): WitnessTransaction =
|
||||
lockTime: UInt32, witness: TransactionWitness): WitnessTransaction =
|
||||
WitnessTransactionImpl(version, inputs, outputs, lockTime, witness)
|
||||
|
||||
override def fromBytes(bytes: Seq[Byte]): WitnessTransaction = RawWitnessTransactionParser.read(bytes)
|
||||
|
@ -36,17 +36,16 @@ sealed abstract class CoinbaseInput extends TransactionInput {
|
||||
|
||||
object TransactionInput extends Factory[TransactionInput] {
|
||||
private case class TransactionInputImpl(
|
||||
previousOutput: TransactionOutPoint,
|
||||
scriptSignature: ScriptSignature, sequence: UInt32
|
||||
) extends TransactionInput
|
||||
previousOutput: TransactionOutPoint,
|
||||
scriptSignature: ScriptSignature, sequence: UInt32) extends TransactionInput
|
||||
def empty: TransactionInput = EmptyTransactionInput
|
||||
|
||||
def fromBytes(bytes: Seq[Byte]): TransactionInput = RawTransactionInputParser.read(bytes)
|
||||
|
||||
def apply(outPoint: TransactionOutPoint, scriptSignature: ScriptSignature,
|
||||
sequenceNumber: UInt32): TransactionInput = outPoint match {
|
||||
sequenceNumber: UInt32): TransactionInput = outPoint match {
|
||||
case EmptyTransactionOutPoint => CoinbaseInput(scriptSignature)
|
||||
case _: TransactionOutPoint => TransactionInputImpl(outPoint, scriptSignature, sequenceNumber)
|
||||
case _: TransactionOutPoint => TransactionInputImpl(outPoint, scriptSignature, sequenceNumber)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -27,8 +27,7 @@ sealed abstract class TransactionOutPoint extends NetworkElement {
|
||||
*/
|
||||
case object EmptyTransactionOutPoint extends TransactionOutPoint {
|
||||
def txId = DoubleSha256Digest(
|
||||
BitcoinSUtil.decodeHex("0000000000000000000000000000000000000000000000000000000000000000")
|
||||
)
|
||||
BitcoinSUtil.decodeHex("0000000000000000000000000000000000000000000000000000000000000000"))
|
||||
def vout = UInt32("ffffffff")
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ object TransactionWitness {
|
||||
def fromWitOpt(witnesses: Seq[Option[ScriptWitness]]): TransactionWitness = {
|
||||
val replaced: Seq[ScriptWitness] = witnesses.map {
|
||||
case Some(wit) => wit
|
||||
case None => EmptyScriptWitness
|
||||
case None => EmptyScriptWitness
|
||||
}
|
||||
TransactionWitness(replaced)
|
||||
}
|
||||
|
@ -72,9 +72,8 @@ object ScriptProgram extends BitcoinSLogger {
|
||||
*/
|
||||
private case class PreExecutionScriptProgramImpl(
|
||||
txSignatureComponent: TxSigComponent,
|
||||
stack: List[ScriptToken], script: List[ScriptToken], originalScript: List[ScriptToken], altStack: List[ScriptToken],
|
||||
flags: Seq[ScriptFlag]
|
||||
) extends PreExecutionScriptProgram
|
||||
stack: List[ScriptToken], script: List[ScriptToken], originalScript: List[ScriptToken], altStack: List[ScriptToken],
|
||||
flags: Seq[ScriptFlag]) extends PreExecutionScriptProgram
|
||||
|
||||
/**
|
||||
* Implementation type for a [[ExecutionInProgressScriptProgram]] - a [[ScriptProgram]] that is currently being
|
||||
@ -82,9 +81,8 @@ object ScriptProgram extends BitcoinSLogger {
|
||||
*/
|
||||
private case class ExecutionInProgressScriptProgramImpl(
|
||||
txSignatureComponent: TxSigComponent,
|
||||
stack: List[ScriptToken], script: List[ScriptToken], originalScript: List[ScriptToken], altStack: List[ScriptToken],
|
||||
flags: Seq[ScriptFlag], lastCodeSeparator: Option[Int]
|
||||
) extends ExecutionInProgressScriptProgram
|
||||
stack: List[ScriptToken], script: List[ScriptToken], originalScript: List[ScriptToken], altStack: List[ScriptToken],
|
||||
flags: Seq[ScriptFlag], lastCodeSeparator: Option[Int]) extends ExecutionInProgressScriptProgram
|
||||
|
||||
/**
|
||||
* The implementation type for a [[ExecutedScriptProgram]] - a [[ScriptProgram]] that has been evaluated completely
|
||||
@ -92,9 +90,8 @@ object ScriptProgram extends BitcoinSLogger {
|
||||
*/
|
||||
private case class ExecutedScriptProgramImpl(
|
||||
txSignatureComponent: TxSigComponent,
|
||||
stack: List[ScriptToken], script: List[ScriptToken], originalScript: List[ScriptToken], altStack: List[ScriptToken],
|
||||
flags: Seq[ScriptFlag], error: Option[ScriptError]
|
||||
) extends ExecutedScriptProgram
|
||||
stack: List[ScriptToken], script: List[ScriptToken], originalScript: List[ScriptToken], altStack: List[ScriptToken],
|
||||
flags: Seq[ScriptFlag], error: Option[ScriptError]) extends ExecutedScriptProgram
|
||||
|
||||
//indicates whether the script or the stack needs to be updated
|
||||
sealed trait UpdateIndicator
|
||||
@ -192,13 +189,12 @@ object ScriptProgram extends BitcoinSLogger {
|
||||
ExecutionInProgressScriptProgramImpl(
|
||||
oldProgram.txSignatureComponent,
|
||||
oldProgram.stack, oldProgram.script, oldProgram.originalScript,
|
||||
oldProgram.altStack, oldProgram.flags, Some(lastCodeSeparator)
|
||||
)
|
||||
oldProgram.altStack, oldProgram.flags, Some(lastCodeSeparator))
|
||||
}
|
||||
|
||||
/** Updates the [[ScriptToken]]s in either the stack or script and the last [[org.bitcoins.core.script.crypto.OP_CODESEPARATOR]] index */
|
||||
def apply(oldProgram: ExecutionInProgressScriptProgram, tokens: Seq[ScriptToken], indicator: UpdateIndicator,
|
||||
lastCodeSeparator: Int): ExecutionInProgressScriptProgram = {
|
||||
lastCodeSeparator: Int): ExecutionInProgressScriptProgram = {
|
||||
val updatedIndicator = ScriptProgram(oldProgram, tokens, indicator)
|
||||
updatedIndicator match {
|
||||
case e: ExecutionInProgressScriptProgram =>
|
||||
@ -210,7 +206,7 @@ object ScriptProgram extends BitcoinSLogger {
|
||||
|
||||
/** Updates the [[Stack]], [[Script]], [[AltStack]] of the given [[ScriptProgram]]. */
|
||||
def apply(oldProgram: ScriptProgram, stack: Seq[ScriptToken], script: Seq[ScriptToken], altStack: Seq[ScriptToken],
|
||||
updateIndicator: UpdateIndicator): ScriptProgram = {
|
||||
updateIndicator: UpdateIndicator): ScriptProgram = {
|
||||
val updatedProgramStack = ScriptProgram(oldProgram, stack, Stack)
|
||||
val updatedProgramScript = ScriptProgram(updatedProgramStack, script, Script)
|
||||
val updatedProgramAltStack = ScriptProgram(updatedProgramScript, altStack, AltStack)
|
||||
@ -228,56 +224,56 @@ object ScriptProgram extends BitcoinSLogger {
|
||||
* @return the script program representing all of this information
|
||||
*/
|
||||
def apply(transaction: WitnessTransaction, scriptPubKey: P2SHScriptPubKey, inputIndex: UInt32,
|
||||
flags: Seq[ScriptFlag], amount: CurrencyUnit): PreExecutionScriptProgram = {
|
||||
flags: Seq[ScriptFlag], amount: CurrencyUnit): PreExecutionScriptProgram = {
|
||||
val script = transaction.inputs(inputIndex.toInt).scriptSignature.asm
|
||||
ScriptProgram(transaction, scriptPubKey, inputIndex, script.toList, flags, amount)
|
||||
}
|
||||
|
||||
def apply(transaction: WitnessTransaction, scriptPubKey: WitnessScriptPubKey, inputIndex: UInt32,
|
||||
flags: Seq[ScriptFlag], amount: CurrencyUnit): PreExecutionScriptProgram = {
|
||||
flags: Seq[ScriptFlag], amount: CurrencyUnit): PreExecutionScriptProgram = {
|
||||
val script = transaction.inputs(inputIndex.toInt).scriptSignature.asm
|
||||
ScriptProgram(transaction, scriptPubKey, inputIndex, script.toList, flags, amount)
|
||||
}
|
||||
|
||||
def apply(transaction: Transaction, scriptPubKey: ScriptPubKey, inputIndex: UInt32,
|
||||
stack: Seq[ScriptToken], script: Seq[ScriptToken], flags: Seq[ScriptFlag]): ScriptProgram = {
|
||||
stack: Seq[ScriptToken], script: Seq[ScriptToken], flags: Seq[ScriptFlag]): ScriptProgram = {
|
||||
val p = ScriptProgram(transaction, scriptPubKey, inputIndex, flags)
|
||||
ScriptProgram(p, stack, script)
|
||||
}
|
||||
|
||||
def apply(transaction: WitnessTransaction, scriptPubKey: P2SHScriptPubKey, inputIndex: UInt32, script: Seq[ScriptToken],
|
||||
flags: Seq[ScriptFlag], amount: CurrencyUnit): PreExecutionScriptProgram = {
|
||||
flags: Seq[ScriptFlag], amount: CurrencyUnit): PreExecutionScriptProgram = {
|
||||
val w = WitnessTxSigComponent(transaction, inputIndex, scriptPubKey, flags, amount)
|
||||
ScriptProgram(w, Nil, script, script, Nil)
|
||||
}
|
||||
|
||||
def apply(transaction: WitnessTransaction, scriptPubKey: WitnessScriptPubKey, inputIndex: UInt32, script: Seq[ScriptToken],
|
||||
flags: Seq[ScriptFlag], amount: CurrencyUnit): PreExecutionScriptProgram = {
|
||||
flags: Seq[ScriptFlag], amount: CurrencyUnit): PreExecutionScriptProgram = {
|
||||
val w = WitnessTxSigComponent(transaction, inputIndex, scriptPubKey, flags, amount)
|
||||
ScriptProgram(w, Nil, script, script, Nil)
|
||||
}
|
||||
|
||||
def apply(t: TxSigComponent, stack: Seq[ScriptToken], script: Seq[ScriptToken], originalScript: Seq[ScriptToken],
|
||||
altStack: Seq[ScriptToken]): PreExecutionScriptProgram = {
|
||||
altStack: Seq[ScriptToken]): PreExecutionScriptProgram = {
|
||||
ScriptProgram(t, stack.toList, script.toList, originalScript.toList, altStack.toList, t.flags)
|
||||
}
|
||||
|
||||
def apply(transaction: WitnessTransaction, scriptPubKey: WitnessScriptPubKey, inputIndex: UInt32, stack: Seq[ScriptToken],
|
||||
script: Seq[ScriptToken], flags: Seq[ScriptFlag], witness: ScriptWitness,
|
||||
amount: CurrencyUnit): ScriptProgram = {
|
||||
script: Seq[ScriptToken], flags: Seq[ScriptFlag], witness: ScriptWitness,
|
||||
amount: CurrencyUnit): ScriptProgram = {
|
||||
val program = ScriptProgram(transaction, scriptPubKey, inputIndex, flags, amount)
|
||||
ScriptProgram(program, stack, script)
|
||||
}
|
||||
|
||||
def apply(transaction: WitnessTransaction, scriptPubKey: P2SHScriptPubKey, inputIndex: UInt32, stack: Seq[ScriptToken],
|
||||
script: Seq[ScriptToken], flags: Seq[ScriptFlag], witness: ScriptWitness,
|
||||
amount: CurrencyUnit): ScriptProgram = {
|
||||
script: Seq[ScriptToken], flags: Seq[ScriptFlag], witness: ScriptWitness,
|
||||
amount: CurrencyUnit): ScriptProgram = {
|
||||
val program = ScriptProgram(transaction, scriptPubKey, inputIndex, flags, amount)
|
||||
ScriptProgram(program, stack, script)
|
||||
}
|
||||
|
||||
def apply(txSignatureComponent: TxSigComponent, stack: Seq[ScriptToken], script: Seq[ScriptToken],
|
||||
originalScript: Seq[ScriptToken]): ScriptProgram = {
|
||||
originalScript: Seq[ScriptToken]): ScriptProgram = {
|
||||
ScriptProgram(txSignatureComponent, stack.toList, script.toList, originalScript.toList, Nil)
|
||||
}
|
||||
|
||||
@ -288,30 +284,30 @@ object ScriptProgram extends BitcoinSLogger {
|
||||
|
||||
/** Creates a fresh [[PreExecutionScriptProgram]] */
|
||||
def apply(transaction: WitnessTransaction, scriptPubKey: WitnessScriptPubKey, inputIndex: UInt32, stack: Seq[ScriptToken],
|
||||
script: Seq[ScriptToken], originalScript: Seq[ScriptToken], altStack: Seq[ScriptToken],
|
||||
flags: Seq[ScriptFlag], amount: CurrencyUnit): PreExecutionScriptProgram = {
|
||||
script: Seq[ScriptToken], originalScript: Seq[ScriptToken], altStack: Seq[ScriptToken],
|
||||
flags: Seq[ScriptFlag], amount: CurrencyUnit): PreExecutionScriptProgram = {
|
||||
val t = WitnessTxSigComponent(transaction, inputIndex,
|
||||
scriptPubKey, flags, amount)
|
||||
ScriptProgram(t, stack.toList, script.toList, originalScript.toList, altStack.toList, flags)
|
||||
}
|
||||
|
||||
def apply(transaction: WitnessTransaction, scriptPubKey: P2SHScriptPubKey, inputIndex: UInt32, stack: Seq[ScriptToken],
|
||||
script: Seq[ScriptToken], originalScript: Seq[ScriptToken], altStack: Seq[ScriptToken],
|
||||
flags: Seq[ScriptFlag], amount: CurrencyUnit): PreExecutionScriptProgram = {
|
||||
script: Seq[ScriptToken], originalScript: Seq[ScriptToken], altStack: Seq[ScriptToken],
|
||||
flags: Seq[ScriptFlag], amount: CurrencyUnit): PreExecutionScriptProgram = {
|
||||
val t = WitnessTxSigComponent(transaction, inputIndex,
|
||||
scriptPubKey, flags, amount)
|
||||
ScriptProgram(t, stack.toList, script.toList, originalScript.toList, altStack.toList, flags)
|
||||
}
|
||||
|
||||
def apply(transaction: BaseTransaction, scriptPubKey: ScriptPubKey, inputIndex: UInt32, stack: Seq[ScriptToken],
|
||||
script: Seq[ScriptToken], originalScript: Seq[ScriptToken], altStack: Seq[ScriptToken],
|
||||
flags: Seq[ScriptFlag]): PreExecutionScriptProgram = {
|
||||
script: Seq[ScriptToken], originalScript: Seq[ScriptToken], altStack: Seq[ScriptToken],
|
||||
flags: Seq[ScriptFlag]): PreExecutionScriptProgram = {
|
||||
val t = BaseTxSigComponent(transaction, inputIndex, scriptPubKey, flags)
|
||||
ScriptProgram(t, stack.toList, script.toList, originalScript.toList, altStack.toList, flags)
|
||||
}
|
||||
|
||||
def apply(t: TxSigComponent, stack: Seq[ScriptToken], script: Seq[ScriptToken], originalScript: Seq[ScriptToken],
|
||||
altStack: Seq[ScriptToken], flags: Seq[ScriptFlag]): PreExecutionScriptProgram = {
|
||||
altStack: Seq[ScriptToken], flags: Seq[ScriptFlag]): PreExecutionScriptProgram = {
|
||||
PreExecutionScriptProgramImpl(t, stack.toList, script.toList, originalScript.toList, altStack.toList, flags)
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ sealed abstract class ArithmeticInterpreter {
|
||||
require(program.script.headOption.contains(OP_ABS), "Script top must be OP_ABS")
|
||||
performUnaryArithmeticOperation(program, x => x match {
|
||||
case ScriptNumber.zero => ScriptNumber.zero
|
||||
case _: ScriptNumber => ScriptNumber(x.toLong.abs)
|
||||
case _: ScriptNumber => ScriptNumber(x.toLong.abs)
|
||||
})
|
||||
}
|
||||
|
||||
@ -93,8 +93,7 @@ sealed abstract class ArithmeticInterpreter {
|
||||
def opNumEqualVerify(program: ScriptProgram): ScriptProgram = {
|
||||
require(
|
||||
program.script.headOption.contains(OP_NUMEQUALVERIFY),
|
||||
"Script top must be OP_NUMEQUALVERIFY"
|
||||
)
|
||||
"Script top must be OP_NUMEQUALVERIFY")
|
||||
if (program.stack.size < 2) {
|
||||
logger.error("OP_NUMEQUALVERIFY requires two stack elements")
|
||||
ScriptProgram(program, ScriptErrorInvalidStackOperation)
|
||||
@ -116,8 +115,7 @@ sealed abstract class ArithmeticInterpreter {
|
||||
def opNumNotEqual(program: ScriptProgram): ScriptProgram = {
|
||||
require(
|
||||
program.script.headOption.contains(OP_NUMNOTEQUAL),
|
||||
"Script top must be OP_NUMNOTEQUAL"
|
||||
)
|
||||
"Script top must be OP_NUMNOTEQUAL")
|
||||
performBinaryBooleanOperation(program, (x, y) => {
|
||||
x.toLong != y.toLong
|
||||
})
|
||||
@ -127,8 +125,7 @@ sealed abstract class ArithmeticInterpreter {
|
||||
def opLessThan(program: ScriptProgram): ScriptProgram = {
|
||||
require(
|
||||
program.script.headOption.contains(OP_LESSTHAN),
|
||||
"Script top must be OP_LESSTHAN"
|
||||
)
|
||||
"Script top must be OP_LESSTHAN")
|
||||
performBinaryBooleanOperation(program, (x, y) => y < x)
|
||||
}
|
||||
|
||||
@ -136,8 +133,7 @@ sealed abstract class ArithmeticInterpreter {
|
||||
def opGreaterThan(program: ScriptProgram): ScriptProgram = {
|
||||
require(
|
||||
program.script.headOption.contains(OP_GREATERTHAN),
|
||||
"Script top must be OP_GREATERTHAN"
|
||||
)
|
||||
"Script top must be OP_GREATERTHAN")
|
||||
performBinaryBooleanOperation(program, (x, y) => y > x)
|
||||
}
|
||||
|
||||
@ -145,8 +141,7 @@ sealed abstract class ArithmeticInterpreter {
|
||||
def opLessThanOrEqual(program: ScriptProgram): ScriptProgram = {
|
||||
require(
|
||||
program.script.headOption.contains(OP_LESSTHANOREQUAL),
|
||||
"Script top must be OP_LESSTHANOREQUAL"
|
||||
)
|
||||
"Script top must be OP_LESSTHANOREQUAL")
|
||||
performBinaryBooleanOperation(program, (x, y) => y <= x)
|
||||
}
|
||||
|
||||
@ -154,8 +149,7 @@ sealed abstract class ArithmeticInterpreter {
|
||||
def opGreaterThanOrEqual(program: ScriptProgram): ScriptProgram = {
|
||||
require(
|
||||
program.script.headOption.contains(OP_GREATERTHANOREQUAL),
|
||||
"Script top must be OP_GREATERTHANOREQUAL"
|
||||
)
|
||||
"Script top must be OP_GREATERTHANOREQUAL")
|
||||
performBinaryBooleanOperation(program, (x, y) => y >= x)
|
||||
}
|
||||
|
||||
@ -163,8 +157,7 @@ sealed abstract class ArithmeticInterpreter {
|
||||
def opMin(program: ScriptProgram): ScriptProgram = {
|
||||
require(
|
||||
program.script.headOption.contains(OP_MIN),
|
||||
"Script top must be OP_MIN"
|
||||
)
|
||||
"Script top must be OP_MIN")
|
||||
if (program.stack.size < 2) {
|
||||
logger.error("OP_MAX requires at least two stack elements")
|
||||
ScriptProgram(program, ScriptErrorInvalidStackOperation)
|
||||
@ -177,8 +170,7 @@ sealed abstract class ArithmeticInterpreter {
|
||||
def opMax(program: ScriptProgram): ScriptProgram = {
|
||||
require(
|
||||
program.script.headOption.contains(OP_MAX),
|
||||
"Script top must be OP_MAX"
|
||||
)
|
||||
"Script top must be OP_MAX")
|
||||
if (program.stack.size < 2) {
|
||||
logger.error("OP_MAX requires at least two stack elements")
|
||||
ScriptProgram(program, ScriptErrorInvalidStackOperation)
|
||||
@ -191,8 +183,7 @@ sealed abstract class ArithmeticInterpreter {
|
||||
def opWithin(program: ScriptProgram): ScriptProgram = {
|
||||
require(
|
||||
program.script.headOption.contains(OP_WITHIN),
|
||||
"Script top must be OP_WITHIN"
|
||||
)
|
||||
"Script top must be OP_WITHIN")
|
||||
if (program.stack.size < 3) {
|
||||
logger.error("OP_WITHIN requires at least 3 elements on the stack")
|
||||
ScriptProgram(program, ScriptErrorInvalidStackOperation)
|
||||
@ -354,8 +345,7 @@ sealed abstract class ArithmeticInterpreter {
|
||||
*/
|
||||
private def performComparisonOnTwoStackTopItems(
|
||||
program: ScriptProgram,
|
||||
op: (ScriptNumber, ScriptNumber) => ScriptNumber
|
||||
): ScriptProgram = {
|
||||
op: (ScriptNumber, ScriptNumber) => ScriptNumber): ScriptProgram = {
|
||||
performBinaryArithmeticOperation(program, op)
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ object BytesToPushOntoStack extends ScriptOperationFactory[BytesToPushOntoStack]
|
||||
val bytesToPushOntoStackOpt = operations.find(_.opCode == num)
|
||||
bytesToPushOntoStackOpt match {
|
||||
case Some(bytesToPushOntoStack) => bytesToPushOntoStack
|
||||
case None => throw new IllegalArgumentException("We cannot have a BytesToPushOntoStack for greater than 75 bytes")
|
||||
case None => throw new IllegalArgumentException("We cannot have a BytesToPushOntoStack for greater than 75 bytes")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ sealed abstract class ConstantInterpreter {
|
||||
//for the case when a ScriptNumberImpl(x) was parsed as a ByteToPushOntoStackImpl(x)
|
||||
val scriptToken = scriptTokens.head match {
|
||||
case x: BytesToPushOntoStack => ScriptNumber(x.opCode)
|
||||
case x => x
|
||||
case x => x
|
||||
}
|
||||
takeUntilBytesNeeded(scriptTokens.tail, scriptToken :: accum)
|
||||
}
|
||||
@ -57,7 +57,7 @@ sealed abstract class ConstantInterpreter {
|
||||
|
||||
val (newScript, bytesToPushOntoStack) = program.script.head match {
|
||||
case OP_PUSHDATA1 | OP_PUSHDATA2 | OP_PUSHDATA4 => takeUntilBytesNeeded(program.script.tail.tail, Nil)
|
||||
case _: ScriptToken => takeUntilBytesNeeded(program.script.tail, Nil)
|
||||
case _: ScriptToken => takeUntilBytesNeeded(program.script.tail, Nil)
|
||||
}
|
||||
logger.debug("new script: " + newScript)
|
||||
logger.debug("Bytes to push onto stack: " + bytesToPushOntoStack)
|
||||
@ -95,7 +95,7 @@ sealed abstract class ConstantInterpreter {
|
||||
//for instance OP_PUSHDATA1 OP_0
|
||||
val scriptNumOp = program.script(1).bytes match {
|
||||
case h :: t => ScriptNumberOperation.fromNumber(h.toInt)
|
||||
case Nil => None
|
||||
case Nil => None
|
||||
}
|
||||
if (ScriptFlagUtil.requireMinimalData(program.flags) && program.script(1).bytes.size == 1 &&
|
||||
scriptNumOp.isDefined) {
|
||||
@ -122,7 +122,7 @@ sealed abstract class ConstantInterpreter {
|
||||
private def bytesNeededForPushOp(token: ScriptToken): Long = token match {
|
||||
case scriptNumber: BytesToPushOntoStack => scriptNumber.opCode
|
||||
case scriptNumOp: ScriptNumberOperation => scriptNumOp.opCode
|
||||
case scriptNumber: ScriptNumber => scriptNumber.toLong
|
||||
case scriptNumber: ScriptNumber => scriptNumber.toLong
|
||||
case scriptConstant: ScriptConstant =>
|
||||
val constantFlippedEndianness = BitcoinSUtil.flipEndianness(scriptConstant.hex)
|
||||
java.lang.Long.parseLong(constantFlippedEndianness, 16)
|
||||
|
@ -51,7 +51,7 @@ sealed abstract class ControlOperationsInterpreter {
|
||||
}
|
||||
/** Checks if the stack top is NOT minimially encoded */
|
||||
private def isNotMinimalStackTop(stackTopOpt: Option[ScriptToken], sigVersion: SignatureVersion,
|
||||
minimalIfEnabled: Boolean): Boolean = {
|
||||
minimalIfEnabled: Boolean): Boolean = {
|
||||
//see: https://github.com/bitcoin/bitcoin/blob/528472111b4965b1a99c4bcf08ac5ec93d87f10f/src/script/interpreter.cpp#L447-L452
|
||||
//https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-August/013014.html
|
||||
val isNotMinimal = stackTopOpt.map { stackTop =>
|
||||
@ -92,7 +92,7 @@ sealed abstract class ControlOperationsInterpreter {
|
||||
} else {
|
||||
val tree = parseBinaryTree(program.script)
|
||||
val treeWithNextOpElseRemoved = tree match {
|
||||
case Empty => Empty
|
||||
case Empty => Empty
|
||||
case leaf: Leaf[ScriptToken] => leaf
|
||||
case node: Node[ScriptToken] =>
|
||||
removeFirstOpElse(node)
|
||||
@ -160,8 +160,7 @@ sealed abstract class ControlOperationsInterpreter {
|
||||
/** The loop that parses a list of [[ScriptToken]]s into a [[BinaryTree]]. */
|
||||
private def parse(
|
||||
script: List[ScriptToken],
|
||||
tree: BinaryTree[ScriptToken]
|
||||
): (BinaryTree[ScriptToken], List[ScriptToken]) = script match {
|
||||
tree: BinaryTree[ScriptToken]): (BinaryTree[ScriptToken], List[ScriptToken]) = script match {
|
||||
case OP_ENDIF :: t =>
|
||||
val ifTree = insertSubTree(tree, Leaf(OP_ENDIF))
|
||||
(ifTree, t)
|
||||
@ -172,7 +171,7 @@ sealed abstract class ControlOperationsInterpreter {
|
||||
case h :: t if h == OP_ELSE =>
|
||||
val (subTree, remaining) = parse(t, Node(OP_ELSE, Empty, Empty))
|
||||
val opElseTree = tree match {
|
||||
case Empty => subTree
|
||||
case Empty => subTree
|
||||
case l: Leaf[ScriptToken] => Node(l.v, Empty, subTree)
|
||||
case n: Node[ScriptToken] => Node(n.v, n.l, insertSubTree(n.r, subTree))
|
||||
}
|
||||
@ -191,9 +190,8 @@ sealed abstract class ControlOperationsInterpreter {
|
||||
*/
|
||||
//@tailrec
|
||||
private def insertSubTree(
|
||||
tree: BinaryTree[ScriptToken],
|
||||
subTree: BinaryTree[ScriptToken]
|
||||
): BinaryTree[ScriptToken] = tree match {
|
||||
tree: BinaryTree[ScriptToken],
|
||||
subTree: BinaryTree[ScriptToken]): BinaryTree[ScriptToken] = tree match {
|
||||
case Empty => subTree
|
||||
case leaf: Leaf[ScriptToken] =>
|
||||
if (subTree == Empty) leaf
|
||||
@ -215,12 +213,12 @@ sealed abstract class ControlOperationsInterpreter {
|
||||
def checkMatchingOpIfOpNotIfOpEndIf(script: List[ScriptToken]): Boolean = {
|
||||
@tailrec
|
||||
def loop(script: List[ScriptToken], counter: Int): Boolean = script match {
|
||||
case _ if (counter < 0) => false
|
||||
case OP_ENDIF :: t => loop(t, counter - 1)
|
||||
case OP_IF :: t => loop(t, counter + 1)
|
||||
case OP_NOTIF :: t => loop(t, counter + 1)
|
||||
case _ if (counter < 0) => false
|
||||
case OP_ENDIF :: t => loop(t, counter - 1)
|
||||
case OP_IF :: t => loop(t, counter + 1)
|
||||
case OP_NOTIF :: t => loop(t, counter + 1)
|
||||
case (_: ScriptToken) :: t => loop(t, counter)
|
||||
case Nil => counter == 0
|
||||
case Nil => counter == 0
|
||||
}
|
||||
loop(script, 0)
|
||||
}
|
||||
@ -230,7 +228,7 @@ sealed abstract class ControlOperationsInterpreter {
|
||||
val index = script.indexOf(OP_ENDIF)
|
||||
index match {
|
||||
case -1 => None
|
||||
case _ => Some(index)
|
||||
case _ => Some(index)
|
||||
}
|
||||
}
|
||||
|
||||
@ -246,7 +244,7 @@ sealed abstract class ControlOperationsInterpreter {
|
||||
val index = script.indexOf(OP_ELSE)
|
||||
index match {
|
||||
case -1 => None
|
||||
case _ => Some(index)
|
||||
case _ => Some(index)
|
||||
}
|
||||
}
|
||||
|
||||
@ -259,14 +257,14 @@ sealed abstract class ControlOperationsInterpreter {
|
||||
def removeFirstOpElse(tree: BinaryTree[ScriptToken]): BinaryTree[ScriptToken] = {
|
||||
//@tailrec
|
||||
def loop(child: BinaryTree[ScriptToken], parent: Node[ScriptToken]): BinaryTree[ScriptToken] = child match {
|
||||
case Empty => Empty
|
||||
case Empty => Empty
|
||||
case l: Leaf[ScriptToken] => l
|
||||
case Node(OP_ELSE, _, r) => r
|
||||
case Node(OP_ELSE, _, r) => r
|
||||
case n: Node[ScriptToken] =>
|
||||
Node(n.v, n.l, loop(n.r, n))
|
||||
}
|
||||
tree match {
|
||||
case Empty => Empty
|
||||
case Empty => Empty
|
||||
case l: Leaf[ScriptToken] => l
|
||||
case n: Node[ScriptToken] =>
|
||||
val result = Node(n.v, n.l, loop(n.r, n))
|
||||
|
@ -74,8 +74,7 @@ sealed abstract class CryptoInterpreter {
|
||||
logger.debug("Program after removing OP_CODESEPARATOR: " + removedOpCodeSeparatorsScript)
|
||||
val result = TransactionSignatureChecker.checkSignature(
|
||||
executionInProgressScriptProgram.txSignatureComponent,
|
||||
removedOpCodeSeparatorsScript, pubKey, signature, flags
|
||||
)
|
||||
removedOpCodeSeparatorsScript, pubKey, signature, flags)
|
||||
handleSignatureValidation(program, result, restOfStack)
|
||||
}
|
||||
}
|
||||
@ -85,8 +84,7 @@ sealed abstract class CryptoInterpreter {
|
||||
def opCheckSigVerify(program: ScriptProgram): ScriptProgram = {
|
||||
require(
|
||||
program.script.headOption.contains(OP_CHECKSIGVERIFY),
|
||||
"Script top must be OP_CHECKSIGVERIFY"
|
||||
)
|
||||
"Script top must be OP_CHECKSIGVERIFY")
|
||||
if (program.stack.size < 2) {
|
||||
logger.error("Stack must contain at least 3 items for OP_CHECKSIGVERIFY")
|
||||
ScriptProgram(program, ScriptErrorInvalidStackOperation)
|
||||
@ -173,8 +171,7 @@ sealed abstract class CryptoInterpreter {
|
||||
val (pubKeysScriptTokens, stackWithoutPubKeys) =
|
||||
(
|
||||
program.stack.tail.slice(0, nPossibleSignatures.toInt),
|
||||
program.stack.tail.slice(nPossibleSignatures.toInt, program.stack.tail.size)
|
||||
)
|
||||
program.stack.tail.slice(nPossibleSignatures.toInt, program.stack.tail.size))
|
||||
|
||||
val pubKeys = pubKeysScriptTokens.map(key => ECPublicKey(key.bytes))
|
||||
logger.debug("Public keys on the stack: " + pubKeys)
|
||||
@ -184,8 +181,7 @@ sealed abstract class CryptoInterpreter {
|
||||
//+1 is for the fact that we have the # of sigs + the script token indicating the # of sigs
|
||||
val signaturesScriptTokens = program.stack.tail.slice(
|
||||
nPossibleSignatures.toInt + 1,
|
||||
nPossibleSignatures.toInt + mRequiredSignatures.toInt + 1
|
||||
)
|
||||
nPossibleSignatures.toInt + mRequiredSignatures.toInt + 1)
|
||||
val signatures = signaturesScriptTokens.map(token => ECDigitalSignature(token.bytes))
|
||||
logger.debug("Signatures on the stack: " + signatures)
|
||||
|
||||
@ -214,8 +210,7 @@ sealed abstract class CryptoInterpreter {
|
||||
TransactionSignatureChecker.multiSignatureEvaluator(
|
||||
executionInProgressScriptProgram.txSignatureComponent,
|
||||
removedOpCodeSeparatorsScript, signatures,
|
||||
pubKeys, flags, mRequiredSignatures.toLong
|
||||
)
|
||||
pubKeys, flags, mRequiredSignatures.toLong)
|
||||
|
||||
//remove the extra OP_0 (null dummy) for OP_CHECKMULTISIG from the stack
|
||||
val restOfStack = stackWithoutPubKeysAndSignatures.tail
|
||||
|
@ -37,7 +37,7 @@ object HashType extends Factory[HashType] {
|
||||
/** Returns a hashtype's default byte value */
|
||||
def byte(hashType: HashType): Byte = hashType match {
|
||||
case _: SIGHASH_ALL => sigHashAllByte
|
||||
case h: HashType => h.byte
|
||||
case h: HashType => h.byte
|
||||
}
|
||||
|
||||
def isSIGHASH_ALL_ONE(num: Int32): Boolean = (num & Int32(0x1f)) == Int32(1)
|
||||
|
@ -218,7 +218,7 @@ sealed abstract class ScriptInterpreter {
|
||||
* [[https://github.com/bitcoin/bitcoin/blob/f8528134fc188abc5c7175a19680206964a8fade/src/script/interpreter.cpp#L1302]]
|
||||
*/
|
||||
private def verifyWitnessProgram(witnessVersion: WitnessVersion, scriptWitness: ScriptWitness, witnessProgram: Seq[ScriptToken],
|
||||
wTxSigComponent: WitnessTxSigComponent): Try[ExecutedScriptProgram] = {
|
||||
wTxSigComponent: WitnessTxSigComponent): Try[ExecutedScriptProgram] = {
|
||||
|
||||
/** Helper function to run the post segwit execution checks */
|
||||
def postSegWitProgramChecks(evaluated: ExecutedScriptProgram): ExecutedScriptProgram = {
|
||||
@ -307,84 +307,84 @@ sealed abstract class ScriptInterpreter {
|
||||
loop(ScriptProgram(p, ScriptErrorStackSize), opCount)
|
||||
|
||||
//stack operations
|
||||
case OP_DUP :: t => loop(StackInterpreter.opDup(p), calcOpCount(opCount, OP_DUP))
|
||||
case OP_DEPTH :: t => loop(StackInterpreter.opDepth(p), calcOpCount(opCount, OP_DEPTH))
|
||||
case OP_TOALTSTACK :: t => loop(StackInterpreter.opToAltStack(p), calcOpCount(opCount, OP_TOALTSTACK))
|
||||
case OP_FROMALTSTACK :: t => loop(StackInterpreter.opFromAltStack(p), calcOpCount(opCount, OP_FROMALTSTACK))
|
||||
case OP_DROP :: t => loop(StackInterpreter.opDrop(p), calcOpCount(opCount, OP_DROP))
|
||||
case OP_IFDUP :: t => loop(StackInterpreter.opIfDup(p), calcOpCount(opCount, OP_IFDUP))
|
||||
case OP_NIP :: t => loop(StackInterpreter.opNip(p), calcOpCount(opCount, OP_NIP))
|
||||
case OP_OVER :: t => loop(StackInterpreter.opOver(p), calcOpCount(opCount, OP_OVER))
|
||||
case OP_PICK :: t => loop(StackInterpreter.opPick(p), calcOpCount(opCount, OP_PICK))
|
||||
case OP_ROLL :: t => loop(StackInterpreter.opRoll(p), calcOpCount(opCount, OP_ROLL))
|
||||
case OP_ROT :: t => loop(StackInterpreter.opRot(p), calcOpCount(opCount, OP_ROT))
|
||||
case OP_2ROT :: t => loop(StackInterpreter.op2Rot(p), calcOpCount(opCount, OP_2ROT))
|
||||
case OP_2DROP :: t => loop(StackInterpreter.op2Drop(p), calcOpCount(opCount, OP_2DROP))
|
||||
case OP_SWAP :: t => loop(StackInterpreter.opSwap(p), calcOpCount(opCount, OP_SWAP))
|
||||
case OP_TUCK :: t => loop(StackInterpreter.opTuck(p), calcOpCount(opCount, OP_TUCK))
|
||||
case OP_2DUP :: t => loop(StackInterpreter.op2Dup(p), calcOpCount(opCount, OP_2DUP))
|
||||
case OP_3DUP :: t => loop(StackInterpreter.op3Dup(p), calcOpCount(opCount, OP_3DUP))
|
||||
case OP_2OVER :: t => loop(StackInterpreter.op2Over(p), calcOpCount(opCount, OP_2OVER))
|
||||
case OP_2SWAP :: t => loop(StackInterpreter.op2Swap(p), calcOpCount(opCount, OP_2SWAP))
|
||||
case OP_DUP :: t => loop(StackInterpreter.opDup(p), calcOpCount(opCount, OP_DUP))
|
||||
case OP_DEPTH :: t => loop(StackInterpreter.opDepth(p), calcOpCount(opCount, OP_DEPTH))
|
||||
case OP_TOALTSTACK :: t => loop(StackInterpreter.opToAltStack(p), calcOpCount(opCount, OP_TOALTSTACK))
|
||||
case OP_FROMALTSTACK :: t => loop(StackInterpreter.opFromAltStack(p), calcOpCount(opCount, OP_FROMALTSTACK))
|
||||
case OP_DROP :: t => loop(StackInterpreter.opDrop(p), calcOpCount(opCount, OP_DROP))
|
||||
case OP_IFDUP :: t => loop(StackInterpreter.opIfDup(p), calcOpCount(opCount, OP_IFDUP))
|
||||
case OP_NIP :: t => loop(StackInterpreter.opNip(p), calcOpCount(opCount, OP_NIP))
|
||||
case OP_OVER :: t => loop(StackInterpreter.opOver(p), calcOpCount(opCount, OP_OVER))
|
||||
case OP_PICK :: t => loop(StackInterpreter.opPick(p), calcOpCount(opCount, OP_PICK))
|
||||
case OP_ROLL :: t => loop(StackInterpreter.opRoll(p), calcOpCount(opCount, OP_ROLL))
|
||||
case OP_ROT :: t => loop(StackInterpreter.opRot(p), calcOpCount(opCount, OP_ROT))
|
||||
case OP_2ROT :: t => loop(StackInterpreter.op2Rot(p), calcOpCount(opCount, OP_2ROT))
|
||||
case OP_2DROP :: t => loop(StackInterpreter.op2Drop(p), calcOpCount(opCount, OP_2DROP))
|
||||
case OP_SWAP :: t => loop(StackInterpreter.opSwap(p), calcOpCount(opCount, OP_SWAP))
|
||||
case OP_TUCK :: t => loop(StackInterpreter.opTuck(p), calcOpCount(opCount, OP_TUCK))
|
||||
case OP_2DUP :: t => loop(StackInterpreter.op2Dup(p), calcOpCount(opCount, OP_2DUP))
|
||||
case OP_3DUP :: t => loop(StackInterpreter.op3Dup(p), calcOpCount(opCount, OP_3DUP))
|
||||
case OP_2OVER :: t => loop(StackInterpreter.op2Over(p), calcOpCount(opCount, OP_2OVER))
|
||||
case OP_2SWAP :: t => loop(StackInterpreter.op2Swap(p), calcOpCount(opCount, OP_2SWAP))
|
||||
|
||||
//arithmetic operations
|
||||
case OP_ADD :: t => loop(ArithmeticInterpreter.opAdd(p), calcOpCount(opCount, OP_ADD))
|
||||
case OP_1ADD :: t => loop(ArithmeticInterpreter.op1Add(p), calcOpCount(opCount, OP_1ADD))
|
||||
case OP_1SUB :: t => loop(ArithmeticInterpreter.op1Sub(p), calcOpCount(opCount, OP_1SUB))
|
||||
case OP_SUB :: t => loop(ArithmeticInterpreter.opSub(p), calcOpCount(opCount, OP_SUB))
|
||||
case OP_ABS :: t => loop(ArithmeticInterpreter.opAbs(p), calcOpCount(opCount, OP_ABS))
|
||||
case OP_NEGATE :: t => loop(ArithmeticInterpreter.opNegate(p), calcOpCount(opCount, OP_NEGATE))
|
||||
case OP_NOT :: t => loop(ArithmeticInterpreter.opNot(p), calcOpCount(opCount, OP_NOT))
|
||||
case OP_0NOTEQUAL :: t => loop(ArithmeticInterpreter.op0NotEqual(p), calcOpCount(opCount, OP_0NOTEQUAL))
|
||||
case OP_BOOLAND :: t => loop(ArithmeticInterpreter.opBoolAnd(p), calcOpCount(opCount, OP_BOOLAND))
|
||||
case OP_BOOLOR :: t => loop(ArithmeticInterpreter.opBoolOr(p), calcOpCount(opCount, OP_BOOLOR))
|
||||
case OP_NUMEQUAL :: t => loop(ArithmeticInterpreter.opNumEqual(p), calcOpCount(opCount, OP_NUMEQUAL))
|
||||
case OP_NUMEQUALVERIFY :: t => loop(ArithmeticInterpreter.opNumEqualVerify(p), calcOpCount(opCount, OP_NUMEQUALVERIFY))
|
||||
case OP_NUMNOTEQUAL :: t => loop(ArithmeticInterpreter.opNumNotEqual(p), calcOpCount(opCount, OP_NUMNOTEQUAL))
|
||||
case OP_LESSTHAN :: t => loop(ArithmeticInterpreter.opLessThan(p), calcOpCount(opCount, OP_LESSTHAN))
|
||||
case OP_GREATERTHAN :: t => loop(ArithmeticInterpreter.opGreaterThan(p), calcOpCount(opCount, OP_GREATERTHAN))
|
||||
case OP_LESSTHANOREQUAL :: t => loop(ArithmeticInterpreter.opLessThanOrEqual(p), calcOpCount(opCount, OP_LESSTHANOREQUAL))
|
||||
case OP_ADD :: t => loop(ArithmeticInterpreter.opAdd(p), calcOpCount(opCount, OP_ADD))
|
||||
case OP_1ADD :: t => loop(ArithmeticInterpreter.op1Add(p), calcOpCount(opCount, OP_1ADD))
|
||||
case OP_1SUB :: t => loop(ArithmeticInterpreter.op1Sub(p), calcOpCount(opCount, OP_1SUB))
|
||||
case OP_SUB :: t => loop(ArithmeticInterpreter.opSub(p), calcOpCount(opCount, OP_SUB))
|
||||
case OP_ABS :: t => loop(ArithmeticInterpreter.opAbs(p), calcOpCount(opCount, OP_ABS))
|
||||
case OP_NEGATE :: t => loop(ArithmeticInterpreter.opNegate(p), calcOpCount(opCount, OP_NEGATE))
|
||||
case OP_NOT :: t => loop(ArithmeticInterpreter.opNot(p), calcOpCount(opCount, OP_NOT))
|
||||
case OP_0NOTEQUAL :: t => loop(ArithmeticInterpreter.op0NotEqual(p), calcOpCount(opCount, OP_0NOTEQUAL))
|
||||
case OP_BOOLAND :: t => loop(ArithmeticInterpreter.opBoolAnd(p), calcOpCount(opCount, OP_BOOLAND))
|
||||
case OP_BOOLOR :: t => loop(ArithmeticInterpreter.opBoolOr(p), calcOpCount(opCount, OP_BOOLOR))
|
||||
case OP_NUMEQUAL :: t => loop(ArithmeticInterpreter.opNumEqual(p), calcOpCount(opCount, OP_NUMEQUAL))
|
||||
case OP_NUMEQUALVERIFY :: t => loop(ArithmeticInterpreter.opNumEqualVerify(p), calcOpCount(opCount, OP_NUMEQUALVERIFY))
|
||||
case OP_NUMNOTEQUAL :: t => loop(ArithmeticInterpreter.opNumNotEqual(p), calcOpCount(opCount, OP_NUMNOTEQUAL))
|
||||
case OP_LESSTHAN :: t => loop(ArithmeticInterpreter.opLessThan(p), calcOpCount(opCount, OP_LESSTHAN))
|
||||
case OP_GREATERTHAN :: t => loop(ArithmeticInterpreter.opGreaterThan(p), calcOpCount(opCount, OP_GREATERTHAN))
|
||||
case OP_LESSTHANOREQUAL :: t => loop(ArithmeticInterpreter.opLessThanOrEqual(p), calcOpCount(opCount, OP_LESSTHANOREQUAL))
|
||||
case OP_GREATERTHANOREQUAL :: t => loop(ArithmeticInterpreter.opGreaterThanOrEqual(p), calcOpCount(opCount, OP_GREATERTHANOREQUAL))
|
||||
case OP_MIN :: t => loop(ArithmeticInterpreter.opMin(p), calcOpCount(opCount, OP_MIN))
|
||||
case OP_MAX :: t => loop(ArithmeticInterpreter.opMax(p), calcOpCount(opCount, OP_MAX))
|
||||
case OP_WITHIN :: t => loop(ArithmeticInterpreter.opWithin(p), calcOpCount(opCount, OP_WITHIN))
|
||||
case OP_MIN :: t => loop(ArithmeticInterpreter.opMin(p), calcOpCount(opCount, OP_MIN))
|
||||
case OP_MAX :: t => loop(ArithmeticInterpreter.opMax(p), calcOpCount(opCount, OP_MAX))
|
||||
case OP_WITHIN :: t => loop(ArithmeticInterpreter.opWithin(p), calcOpCount(opCount, OP_WITHIN))
|
||||
|
||||
//bitwise operations
|
||||
case OP_EQUAL :: t => loop(BitwiseInterpreter.opEqual(p), calcOpCount(opCount, OP_EQUAL))
|
||||
case OP_EQUAL :: t => loop(BitwiseInterpreter.opEqual(p), calcOpCount(opCount, OP_EQUAL))
|
||||
|
||||
case OP_EQUALVERIFY :: t => loop(BitwiseInterpreter.opEqualVerify(p), calcOpCount(opCount, OP_EQUALVERIFY))
|
||||
case OP_EQUALVERIFY :: t => loop(BitwiseInterpreter.opEqualVerify(p), calcOpCount(opCount, OP_EQUALVERIFY))
|
||||
|
||||
case OP_0 :: t => loop(ScriptProgram(p, ScriptNumber.zero :: p.stack, t), calcOpCount(opCount, OP_0))
|
||||
case OP_0 :: t => loop(ScriptProgram(p, ScriptNumber.zero :: p.stack, t), calcOpCount(opCount, OP_0))
|
||||
case (scriptNumberOp: ScriptNumberOperation) :: t =>
|
||||
loop(ScriptProgram(p, ScriptNumber(scriptNumberOp.toLong) :: p.stack, t), calcOpCount(opCount, scriptNumberOp))
|
||||
case (bytesToPushOntoStack: BytesToPushOntoStack) :: t =>
|
||||
loop(ConstantInterpreter.pushScriptNumberBytesToStack(p), calcOpCount(opCount, bytesToPushOntoStack))
|
||||
case (scriptNumber: ScriptNumber) :: t =>
|
||||
loop(ScriptProgram(p, scriptNumber :: p.stack, t), calcOpCount(opCount, scriptNumber))
|
||||
case OP_PUSHDATA1 :: t => loop(ConstantInterpreter.opPushData1(p), calcOpCount(opCount, OP_PUSHDATA1))
|
||||
case OP_PUSHDATA2 :: t => loop(ConstantInterpreter.opPushData2(p), calcOpCount(opCount, OP_PUSHDATA2))
|
||||
case OP_PUSHDATA4 :: t => loop(ConstantInterpreter.opPushData4(p), calcOpCount(opCount, OP_PUSHDATA4))
|
||||
case OP_PUSHDATA1 :: t => loop(ConstantInterpreter.opPushData1(p), calcOpCount(opCount, OP_PUSHDATA1))
|
||||
case OP_PUSHDATA2 :: t => loop(ConstantInterpreter.opPushData2(p), calcOpCount(opCount, OP_PUSHDATA2))
|
||||
case OP_PUSHDATA4 :: t => loop(ConstantInterpreter.opPushData4(p), calcOpCount(opCount, OP_PUSHDATA4))
|
||||
|
||||
case (x: ScriptConstant) :: t => loop(ScriptProgram(p, x :: p.stack, t), calcOpCount(opCount, x))
|
||||
|
||||
//control operations
|
||||
case OP_IF :: t => loop(ControlOperationsInterpreter.opIf(p), calcOpCount(opCount, OP_IF))
|
||||
case OP_NOTIF :: t => loop(ControlOperationsInterpreter.opNotIf(p), calcOpCount(opCount, OP_NOTIF))
|
||||
case OP_ELSE :: t => loop(ControlOperationsInterpreter.opElse(p), calcOpCount(opCount, OP_ELSE))
|
||||
case OP_ENDIF :: t => loop(ControlOperationsInterpreter.opEndIf(p), calcOpCount(opCount, OP_ENDIF))
|
||||
case OP_RETURN :: t => loop(ControlOperationsInterpreter.opReturn(p), calcOpCount(opCount, OP_RETURN))
|
||||
case OP_IF :: t => loop(ControlOperationsInterpreter.opIf(p), calcOpCount(opCount, OP_IF))
|
||||
case OP_NOTIF :: t => loop(ControlOperationsInterpreter.opNotIf(p), calcOpCount(opCount, OP_NOTIF))
|
||||
case OP_ELSE :: t => loop(ControlOperationsInterpreter.opElse(p), calcOpCount(opCount, OP_ELSE))
|
||||
case OP_ENDIF :: t => loop(ControlOperationsInterpreter.opEndIf(p), calcOpCount(opCount, OP_ENDIF))
|
||||
case OP_RETURN :: t => loop(ControlOperationsInterpreter.opReturn(p), calcOpCount(opCount, OP_RETURN))
|
||||
|
||||
case OP_VERIFY :: t => loop(ControlOperationsInterpreter.opVerify(p), calcOpCount(opCount, OP_VERIFY))
|
||||
case OP_VERIFY :: t => loop(ControlOperationsInterpreter.opVerify(p), calcOpCount(opCount, OP_VERIFY))
|
||||
|
||||
//crypto operations
|
||||
case OP_HASH160 :: t => loop(CryptoInterpreter.opHash160(p), calcOpCount(opCount, OP_HASH160))
|
||||
case OP_CHECKSIG :: t => loop(CryptoInterpreter.opCheckSig(p), calcOpCount(opCount, OP_CHECKSIG))
|
||||
case OP_CHECKSIGVERIFY :: t => loop(CryptoInterpreter.opCheckSigVerify(p), calcOpCount(opCount, OP_CHECKSIGVERIFY))
|
||||
case OP_SHA1 :: t => loop(CryptoInterpreter.opSha1(p), calcOpCount(opCount, OP_SHA1))
|
||||
case OP_RIPEMD160 :: t => loop(CryptoInterpreter.opRipeMd160(p), calcOpCount(opCount, OP_RIPEMD160))
|
||||
case OP_SHA256 :: t => loop(CryptoInterpreter.opSha256(p), calcOpCount(opCount, OP_SHA256))
|
||||
case OP_HASH256 :: t => loop(CryptoInterpreter.opHash256(p), calcOpCount(opCount, OP_HASH256))
|
||||
case OP_CODESEPARATOR :: t => loop(CryptoInterpreter.opCodeSeparator(p), calcOpCount(opCount, OP_CODESEPARATOR))
|
||||
case OP_HASH160 :: t => loop(CryptoInterpreter.opHash160(p), calcOpCount(opCount, OP_HASH160))
|
||||
case OP_CHECKSIG :: t => loop(CryptoInterpreter.opCheckSig(p), calcOpCount(opCount, OP_CHECKSIG))
|
||||
case OP_CHECKSIGVERIFY :: t => loop(CryptoInterpreter.opCheckSigVerify(p), calcOpCount(opCount, OP_CHECKSIGVERIFY))
|
||||
case OP_SHA1 :: t => loop(CryptoInterpreter.opSha1(p), calcOpCount(opCount, OP_SHA1))
|
||||
case OP_RIPEMD160 :: t => loop(CryptoInterpreter.opRipeMd160(p), calcOpCount(opCount, OP_RIPEMD160))
|
||||
case OP_SHA256 :: t => loop(CryptoInterpreter.opSha256(p), calcOpCount(opCount, OP_SHA256))
|
||||
case OP_HASH256 :: t => loop(CryptoInterpreter.opHash256(p), calcOpCount(opCount, OP_HASH256))
|
||||
case OP_CODESEPARATOR :: t => loop(CryptoInterpreter.opCodeSeparator(p), calcOpCount(opCount, OP_CODESEPARATOR))
|
||||
case OP_CHECKMULTISIG :: t =>
|
||||
CryptoInterpreter.opCheckMultiSig(p) match {
|
||||
case newProgram: ExecutedScriptProgram =>
|
||||
@ -454,7 +454,7 @@ sealed abstract class ScriptInterpreter {
|
||||
} //in this case, just read OP_CSV just like a NOP and remove it from the stack
|
||||
else loop(ScriptProgram(p, p.script.tail, ScriptProgram.Script), calcOpCount(opCount, OP_CHECKSEQUENCEVERIFY))
|
||||
//no more script operations to run, return whether the program is valid and the final state of the program
|
||||
case Nil => loop(ScriptProgram.toExecutedProgram(p), opCount)
|
||||
case Nil => loop(ScriptProgram.toExecutedProgram(p), opCount)
|
||||
case h :: t => throw new RuntimeException(h + " was unmatched")
|
||||
}
|
||||
}
|
||||
@ -495,7 +495,7 @@ sealed abstract class ScriptInterpreter {
|
||||
|
||||
/** Calculates the new op count after the execution of the given [[ScriptToken]] */
|
||||
private def calcOpCount(oldOpCount: Int, token: ScriptToken): Int = BitcoinScriptUtil.countsTowardsScriptOpLimit(token) match {
|
||||
case true => oldOpCount + 1
|
||||
case true => oldOpCount + 1
|
||||
case false => oldOpCount
|
||||
}
|
||||
|
||||
|
@ -29,8 +29,7 @@ sealed abstract class LockTimeInterpreter {
|
||||
final def opCheckLockTimeVerify(program: ScriptProgram): ScriptProgram = {
|
||||
require(
|
||||
program.script.headOption.contains(OP_CHECKLOCKTIMEVERIFY),
|
||||
"Script top must be OP_CHECKLOCKTIMEVERIFY"
|
||||
)
|
||||
"Script top must be OP_CHECKLOCKTIMEVERIFY")
|
||||
val input = program.txSignatureComponent.transaction.inputs(program.txSignatureComponent.inputIndex.toInt)
|
||||
val transaction = program.txSignatureComponent.transaction
|
||||
if (program.stack.size == 0) {
|
||||
@ -238,8 +237,7 @@ sealed abstract class LockTimeInterpreter {
|
||||
(transaction.lockTime < TransactionConstants.locktimeThreshold &&
|
||||
locktime.toLong < TransactionConstants.locktimeThreshold.toLong) ||
|
||||
(transaction.lockTime >= TransactionConstants.locktimeThreshold &&
|
||||
locktime.toLong >= TransactionConstants.locktimeThreshold.toLong)
|
||||
)) return false
|
||||
locktime.toLong >= TransactionConstants.locktimeThreshold.toLong))) return false
|
||||
|
||||
// Now that we know we're comparing apples-to-apples, the
|
||||
// comparison is a simple numeric one.
|
||||
|
@ -20,7 +20,7 @@ sealed abstract class SpliceInterpreter {
|
||||
} else {
|
||||
val scriptNumber = program.stack.head match {
|
||||
case ScriptNumber.zero => ScriptNumber.zero
|
||||
case x: ScriptToken => ScriptNumber(x.bytes.size)
|
||||
case x: ScriptToken => ScriptNumber(x.bytes.size)
|
||||
}
|
||||
ScriptProgram(program, scriptNumber :: program.stack, program.script.tail)
|
||||
}
|
||||
|
@ -20,8 +20,7 @@ sealed abstract class RawMerkleBlockSerializer extends RawBitcoinSerializer[Merk
|
||||
val bytesAfterBlockHeaderParsing = bytes.slice(blockHeader.bytes.size, bytes.size)
|
||||
val transactionCount = UInt32(bytesAfterBlockHeaderParsing.slice(0, 4).reverse)
|
||||
val hashCount = CompactSizeUInt.parseCompactSizeUInt(
|
||||
bytesAfterBlockHeaderParsing.slice(4, bytesAfterBlockHeaderParsing.size)
|
||||
)
|
||||
bytesAfterBlockHeaderParsing.slice(4, bytesAfterBlockHeaderParsing.size))
|
||||
val txHashStartIndex = (4 + hashCount.size).toInt
|
||||
val bytesAfterHashCountParsing = bytesAfterBlockHeaderParsing.slice(txHashStartIndex, bytesAfterBlockHeaderParsing.size)
|
||||
|
||||
@ -52,7 +51,7 @@ sealed abstract class RawMerkleBlockSerializer extends RawBitcoinSerializer[Merk
|
||||
private def parseTransactionHashes(bytes: Seq[Byte], hashCount: CompactSizeUInt): (Seq[DoubleSha256Digest], Seq[Byte]) = {
|
||||
@tailrec
|
||||
def loop(remainingHashes: Long, remainingBytes: Seq[Byte],
|
||||
accum: List[DoubleSha256Digest]): (Seq[DoubleSha256Digest], Seq[Byte]) = {
|
||||
accum: List[DoubleSha256Digest]): (Seq[DoubleSha256Digest], Seq[Byte]) = {
|
||||
if (remainingHashes <= 0) (accum.reverse, remainingBytes)
|
||||
else loop(remainingHashes - 1, remainingBytes.slice(32, remainingBytes.size), DoubleSha256Digest(remainingBytes.take(32)) :: accum)
|
||||
}
|
||||
|
@ -20,8 +20,7 @@ sealed abstract class RawScriptSignatureParser extends RawBitcoinSerializer[Scri
|
||||
//TODO: Figure out a better way to do this, we can theoretically have numbers larger than Int.MaxValue,
|
||||
val scriptSigBytes = bytes.slice(
|
||||
compactSizeUInt.size.toInt,
|
||||
compactSizeUInt.num.toInt + compactSizeUInt.size.toInt
|
||||
)
|
||||
compactSizeUInt.num.toInt + compactSizeUInt.size.toInt)
|
||||
val scriptTokens: List[ScriptToken] = ScriptParser.fromBytes(scriptSigBytes)
|
||||
ScriptSignature.fromAsm(scriptTokens)
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ sealed abstract class ScriptParser extends Factory[List[ScriptToken]] {
|
||||
case h :: t if (h.size > 1 && h.substring(0, 2) == "0x") =>
|
||||
loop(t, BitcoinSUtil.decodeHex(h.substring(2, h.size).toLowerCase).toList.reverse ++ accum)
|
||||
//skip the empty string
|
||||
case h :: t if (h == "") => loop(t, accum)
|
||||
case h :: t if (h == "") => loop(t, accum)
|
||||
case h :: t if (h == "0") => loop(t, OP_0.bytes.toList ++ accum)
|
||||
|
||||
case h :: t if (ScriptOperation.fromString(h).isDefined) =>
|
||||
@ -248,17 +248,15 @@ sealed abstract class ScriptParser extends Factory[List[ScriptToken]] {
|
||||
* @return
|
||||
*/
|
||||
private def buildParsingHelper(op: ScriptOperation, bytesToPushOntoStack: ScriptConstant,
|
||||
scriptConstant: ScriptConstant, restOfBytes: List[Byte], accum: List[ScriptToken]): ParsingHelper[Byte] = {
|
||||
scriptConstant: ScriptConstant, restOfBytes: List[Byte], accum: List[ScriptToken]): ParsingHelper[Byte] = {
|
||||
if (bytesToPushOntoStack.hex == "00") {
|
||||
//if we need to push 0 bytes onto the stack we do not add the script constant
|
||||
ParsingHelper[Byte](
|
||||
restOfBytes,
|
||||
bytesToPushOntoStack :: op :: accum
|
||||
)
|
||||
bytesToPushOntoStack :: op :: accum)
|
||||
} else ParsingHelper[Byte](
|
||||
restOfBytes,
|
||||
scriptConstant :: bytesToPushOntoStack :: op :: accum
|
||||
)
|
||||
scriptConstant :: bytesToPushOntoStack :: op :: accum)
|
||||
}
|
||||
|
||||
/** Checks if a string can be cast to an int */
|
||||
|
@ -24,7 +24,7 @@ sealed abstract class RawTransactionOutPointParser extends RawBitcoinSerializer[
|
||||
//https://github.com/bitcoin/bitcoin/blob/d612837814020ae832499d18e6ee5eb919a87907/src/primitives/transaction.h
|
||||
//http://stackoverflow.com/questions/2711522/what-happens-if-i-assign-a-negative-value-to-an-unsigned-variable
|
||||
val idxBytes = outPoint match {
|
||||
case EmptyTransactionOutPoint => UInt32.max.bytes
|
||||
case EmptyTransactionOutPoint => UInt32.max.bytes
|
||||
case outPoint: TransactionOutPoint => outPoint.vout.bytes
|
||||
}
|
||||
val txIdHex = outPoint.txId.bytes
|
||||
|
@ -73,7 +73,7 @@ sealed abstract class Base58 {
|
||||
|
||||
/** Determines if a string is a valid [[Base58Type]] string. */
|
||||
def isValid(base58: String): Boolean = validityChecks(base58) match {
|
||||
case Success(bool) => bool
|
||||
case Success(bool) => bool
|
||||
case Failure(exception) => false
|
||||
}
|
||||
|
||||
|
@ -8,19 +8,19 @@ trait BinaryTree[+T] {
|
||||
def value: Option[T] = this match {
|
||||
case n: Node[T] => Some(n.v)
|
||||
case l: Leaf[T] => Some(l.v)
|
||||
case Empty => None
|
||||
case Empty => None
|
||||
}
|
||||
|
||||
def left: Option[BinaryTree[T]] = this match {
|
||||
case n: Node[T] => Some(n.l)
|
||||
case l: Leaf[T] => None
|
||||
case Empty => None
|
||||
case Empty => None
|
||||
}
|
||||
|
||||
def right: Option[BinaryTree[T]] = this match {
|
||||
case n: Node[T] => Some(n.r)
|
||||
case l: Leaf[T] => None
|
||||
case Empty => None
|
||||
case Empty => None
|
||||
}
|
||||
|
||||
/**
|
||||
@ -30,8 +30,8 @@ trait BinaryTree[+T] {
|
||||
def toSeqLeafValues: Seq[T] = {
|
||||
@tailrec
|
||||
def loop(tree: BinaryTree[T], accum: List[T], remainder: List[BinaryTree[T]]): Seq[T] = tree match {
|
||||
case Leaf(x) => if (remainder.isEmpty) x :: accum else loop(remainder.head, x :: accum, remainder.tail)
|
||||
case Empty => if (remainder.isEmpty) accum else loop(remainder.head, accum, remainder.tail)
|
||||
case Leaf(x) => if (remainder.isEmpty) x :: accum else loop(remainder.head, x :: accum, remainder.tail)
|
||||
case Empty => if (remainder.isEmpty) accum else loop(remainder.head, accum, remainder.tail)
|
||||
case Node(_, l, r) => loop(l, accum, r :: remainder)
|
||||
}
|
||||
loop(this, List(), List()).reverse
|
||||
@ -42,7 +42,7 @@ trait BinaryTree[+T] {
|
||||
@tailrec
|
||||
def loop(subTree: BinaryTree[T], remainder: List[BinaryTree[T]]): Option[BinaryTree[T]] = {
|
||||
subTree match {
|
||||
case Empty => if (remainder.isEmpty) None else loop(remainder.head, remainder.tail)
|
||||
case Empty => if (remainder.isEmpty) None else loop(remainder.head, remainder.tail)
|
||||
case Leaf(x) => if (f(x)) Some(Leaf(x)) else if (remainder.isEmpty) None else loop(remainder.head, remainder.tail)
|
||||
case Node(v, l, r) =>
|
||||
if (f(v)) Some(Node(v, l, r))
|
||||
@ -77,14 +77,14 @@ trait BinaryTree[+T] {
|
||||
else if (n.r == Empty) Node[T](n.v, n.l, subTree)
|
||||
else throw new RuntimeException("There was no empty branch to insert the new t: " + subTree + "inside of tree: " + parentTree)
|
||||
case l: Leaf[T] => Node(l.v, subTree, Empty)
|
||||
case Empty => subTree
|
||||
case Empty => subTree
|
||||
}
|
||||
|
||||
/** Removes the subTree from the parentTree. */
|
||||
def remove[T](subTree: BinaryTree[T])(parentTree: BinaryTree[T] = this): BinaryTree[T] = {
|
||||
//TODO: Optimize into a tail recursive function
|
||||
parentTree match {
|
||||
case Empty => Empty
|
||||
case Empty => Empty
|
||||
case l: Leaf[T] => if (l == subTree) Empty else l
|
||||
case n: Node[T] =>
|
||||
if (n == subTree) Empty
|
||||
@ -96,14 +96,13 @@ trait BinaryTree[+T] {
|
||||
def replace[T](originalTree: BinaryTree[T], replacementTree: BinaryTree[T])(implicit parentTree: BinaryTree[T] = this): BinaryTree[T] = {
|
||||
//TODO: Optimize this into a tail recursive function
|
||||
parentTree match {
|
||||
case Empty => if (originalTree == Empty) replacementTree else Empty
|
||||
case Empty => if (originalTree == Empty) replacementTree else Empty
|
||||
case l: Leaf[T] => if (l == originalTree) replacementTree else l
|
||||
case n: Node[T] => if (n == originalTree) replacementTree else
|
||||
Node(
|
||||
n.v,
|
||||
replace(originalTree, replacementTree)(n.l),
|
||||
replace(originalTree, replacementTree)(n.r)
|
||||
)
|
||||
replace(originalTree, replacementTree)(n.r))
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,7 +110,7 @@ trait BinaryTree[+T] {
|
||||
@tailrec
|
||||
def loop(tree: BinaryTree[T], accum: List[T], remainder: List[BinaryTree[T]]): List[T] = tree match {
|
||||
case Leaf(x) => if (remainder.isEmpty) accum ++ List(x) else loop(remainder.head, accum ++ List(x), remainder.tail)
|
||||
case Empty => if (remainder.isEmpty) accum else loop(remainder.head, accum, remainder.tail)
|
||||
case Empty => if (remainder.isEmpty) accum else loop(remainder.head, accum, remainder.tail)
|
||||
case Node(v, l, r) =>
|
||||
loop(l, accum ++ List(v), r :: remainder)
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ trait BitcoinSUtil {
|
||||
*/
|
||||
def encodeHex(long: Long): String = {
|
||||
val hex = long.toHexString.length % 2 match {
|
||||
case 1 => "0" + long.toHexString
|
||||
case 1 => "0" + long.toHexString
|
||||
case _: Int => long.toHexString
|
||||
}
|
||||
addPadding(16, hex)
|
||||
@ -29,7 +29,7 @@ trait BitcoinSUtil {
|
||||
|
||||
def encodeHex(int: Int): String = {
|
||||
val hex = int.toHexString.length % 2 match {
|
||||
case 1 => "0" + int.toHexString
|
||||
case 1 => "0" + int.toHexString
|
||||
case _: Int => int.toHexString
|
||||
}
|
||||
addPadding(8, hex)
|
||||
@ -37,7 +37,7 @@ trait BitcoinSUtil {
|
||||
|
||||
def encodeHex(short: Short): String = {
|
||||
val hex = short.toHexString.length % 2 match {
|
||||
case 1 => "0" + short.toHexString
|
||||
case 1 => "0" + short.toHexString
|
||||
case _: Int => short.toHexString
|
||||
}
|
||||
addPadding(4, hex)
|
||||
|
@ -64,9 +64,9 @@ trait BitcoinScriptUtil extends BitcoinSLogger {
|
||||
case (token, index) =>
|
||||
if (multiSigOps.contains(token) && index != 0) {
|
||||
script(index - 1) match {
|
||||
case scriptNum: ScriptNumber => scriptNum.toLong
|
||||
case scriptNum: ScriptNumber => scriptNum.toLong
|
||||
case scriptConstant: ScriptConstant => ScriptNumberUtil.toLong(scriptConstant.hex)
|
||||
case _: ScriptToken => ScriptSettings.maxPublicKeysPerMultiSig
|
||||
case _: ScriptToken => ScriptSettings.maxPublicKeysPerMultiSig
|
||||
}
|
||||
} else 0
|
||||
}.sum
|
||||
@ -82,12 +82,11 @@ trait BitcoinScriptUtil extends BitcoinSLogger {
|
||||
def numPossibleSignaturesOnStack(program: ScriptProgram): ScriptNumber = {
|
||||
require(
|
||||
program.script.headOption == Some(OP_CHECKMULTISIG) || program.script.headOption == Some(OP_CHECKMULTISIGVERIFY),
|
||||
"We can only parse the nubmer of signatures the stack when we are executing a OP_CHECKMULTISIG or OP_CHECKMULTISIGVERIFY op"
|
||||
)
|
||||
"We can only parse the nubmer of signatures the stack when we are executing a OP_CHECKMULTISIG or OP_CHECKMULTISIGVERIFY op")
|
||||
val nPossibleSignatures: ScriptNumber = program.stack.head match {
|
||||
case s: ScriptNumber => s
|
||||
case s: ScriptNumber => s
|
||||
case s: ScriptConstant => ScriptNumber(s.bytes)
|
||||
case _: ScriptToken => throw new RuntimeException("n must be a script number or script constant for OP_CHECKMULTISIG")
|
||||
case _: ScriptToken => throw new RuntimeException("n must be a script number or script constant for OP_CHECKMULTISIG")
|
||||
}
|
||||
nPossibleSignatures
|
||||
}
|
||||
@ -99,14 +98,13 @@ trait BitcoinScriptUtil extends BitcoinSLogger {
|
||||
def numRequiredSignaturesOnStack(program: ScriptProgram): ScriptNumber = {
|
||||
require(
|
||||
program.script.headOption == Some(OP_CHECKMULTISIG) || program.script.headOption == Some(OP_CHECKMULTISIGVERIFY),
|
||||
"We can only parse the nubmer of signatures the stack when we are executing a OP_CHECKMULTISIG or OP_CHECKMULTISIGVERIFY op"
|
||||
)
|
||||
"We can only parse the nubmer of signatures the stack when we are executing a OP_CHECKMULTISIG or OP_CHECKMULTISIGVERIFY op")
|
||||
val nPossibleSignatures = numPossibleSignaturesOnStack(program)
|
||||
val stackWithoutPubKeys = program.stack.tail.slice(nPossibleSignatures.toInt, program.stack.tail.size)
|
||||
val mRequiredSignatures: ScriptNumber = stackWithoutPubKeys.head match {
|
||||
case s: ScriptNumber => s
|
||||
case s: ScriptNumber => s
|
||||
case s: ScriptConstant => ScriptNumber(s.bytes)
|
||||
case _: ScriptToken => throw new RuntimeException("m must be a script number or script constant for OP_CHECKMULTISIG")
|
||||
case _: ScriptToken => throw new RuntimeException("m must be a script number or script constant for OP_CHECKMULTISIG")
|
||||
}
|
||||
mRequiredSignatures
|
||||
}
|
||||
@ -121,7 +119,7 @@ trait BitcoinScriptUtil extends BitcoinSLogger {
|
||||
def loop(tokens: Seq[ScriptToken], accum: List[Boolean]): Seq[Boolean] = tokens match {
|
||||
case h :: t => h match {
|
||||
case scriptOp: ScriptOperation => loop(t, (scriptOp.opCode < OP_16.opCode) :: accum)
|
||||
case _: ScriptToken => loop(t, true :: accum)
|
||||
case _: ScriptToken => loop(t, true :: accum)
|
||||
}
|
||||
case Nil => accum
|
||||
}
|
||||
@ -150,8 +148,8 @@ trait BitcoinScriptUtil extends BitcoinSLogger {
|
||||
case size if (size == 0) => pushOp == OP_0
|
||||
case size if (size == 1 && token.bytes.head == OP_1NEGATE.opCode) =>
|
||||
pushOp == OP_1NEGATE
|
||||
case size if (size <= 75) => token.bytes.size == pushOp.toLong
|
||||
case size if (size <= 255) => pushOp == OP_PUSHDATA1
|
||||
case size if (size <= 75) => token.bytes.size == pushOp.toLong
|
||||
case size if (size <= 255) => pushOp == OP_PUSHDATA1
|
||||
case size if (size <= 65535) => pushOp == OP_PUSHDATA2
|
||||
case size =>
|
||||
//default case is true because we have to use the largest push op as possible which is OP_PUSHDATA4
|
||||
@ -282,8 +280,7 @@ trait BitcoinScriptUtil extends BitcoinSLogger {
|
||||
*/
|
||||
def calculateScriptForChecking(
|
||||
txSignatureComponent: TxSigComponent,
|
||||
signature: ECDigitalSignature, script: Seq[ScriptToken]
|
||||
): Seq[ScriptToken] = {
|
||||
signature: ECDigitalSignature, script: Seq[ScriptToken]): Seq[ScriptToken] = {
|
||||
val scriptForChecking = calculateScriptForSigning(txSignatureComponent, script)
|
||||
logger.debug("sig for removal: " + signature)
|
||||
logger.debug("script: " + script)
|
||||
|
@ -22,7 +22,7 @@ sealed abstract class Signer {
|
||||
* @return
|
||||
*/
|
||||
def sign(signers: Seq[Signer.Sign], output: TransactionOutput, unsignedTx: Transaction,
|
||||
inputIndex: UInt32, hashType: HashType): Either[TxSigComponent, TxBuilderError]
|
||||
inputIndex: UInt32, hashType: HashType): Either[TxSigComponent, TxBuilderError]
|
||||
}
|
||||
|
||||
object Signer {
|
||||
@ -51,7 +51,7 @@ sealed abstract class BitcoinSigner extends Signer
|
||||
sealed abstract class P2PKSigner extends BitcoinSigner {
|
||||
|
||||
override def sign(signers: Seq[Signer.Sign], output: TransactionOutput, unsignedTx: Transaction,
|
||||
inputIndex: UInt32, hashType: HashType): Either[TxSigComponent, TxBuilderError] = {
|
||||
inputIndex: UInt32, hashType: HashType): Either[TxSigComponent, TxBuilderError] = {
|
||||
val spk = output.scriptPubKey
|
||||
if (signers.size != 1) {
|
||||
Right(TxBuilderError.TooManySigners)
|
||||
@ -68,7 +68,7 @@ sealed abstract class P2PKSigner extends BitcoinSigner {
|
||||
case wtx: WitnessTransaction => wtx
|
||||
}
|
||||
val redeemScript = wtx.witness.witnesses(inputIndex.toInt) match {
|
||||
case x: P2WSHWitnessV0 => Left(x.redeemScript)
|
||||
case x: P2WSHWitnessV0 => Left(x.redeemScript)
|
||||
case _: P2WPKHWitnessV0 => Right(TxBuilderError.NoRedeemScript)
|
||||
case EmptyScriptWitness => Right(TxBuilderError.NoWitness)
|
||||
}
|
||||
@ -131,7 +131,7 @@ object P2PKSigner extends P2PKSigner
|
||||
sealed abstract class P2PKHSigner extends BitcoinSigner {
|
||||
|
||||
override def sign(signers: Seq[Signer.Sign], output: TransactionOutput, unsignedTx: Transaction,
|
||||
inputIndex: UInt32, hashType: HashType): Either[TxSigComponent, TxBuilderError] = {
|
||||
inputIndex: UInt32, hashType: HashType): Either[TxSigComponent, TxBuilderError] = {
|
||||
val spk = output.scriptPubKey
|
||||
if (signers.size != 1) {
|
||||
Right(TxBuilderError.TooManySigners)
|
||||
@ -152,7 +152,7 @@ sealed abstract class P2PKHSigner extends BitcoinSigner {
|
||||
}
|
||||
val redeemScript = wtx.witness.witnesses(inputIndex.toInt) match {
|
||||
case EmptyScriptWitness | _: P2WPKHWitnessV0 => Right(TxBuilderError.WrongWitness)
|
||||
case p2wsh: P2WSHWitnessV0 => Left(p2wsh.redeemScript)
|
||||
case p2wsh: P2WSHWitnessV0 => Left(p2wsh.redeemScript)
|
||||
}
|
||||
val sigComponent = WitnessTxSigComponentRaw(wtx, inputIndex, p2wshSPK, flags, amount)
|
||||
val signature = TransactionSignatureCreator.createSig(sigComponent, signer, hashType)
|
||||
@ -243,7 +243,7 @@ sealed abstract class MultiSigSigner extends BitcoinSigner {
|
||||
private val logger = BitcoinSLogger.logger
|
||||
|
||||
override def sign(signersWithPubKeys: Seq[Signer.Sign], output: TransactionOutput, unsignedTx: Transaction,
|
||||
inputIndex: UInt32, hashType: HashType): Either[TxSigComponent, TxBuilderError] = {
|
||||
inputIndex: UInt32, hashType: HashType): Either[TxSigComponent, TxBuilderError] = {
|
||||
val spk = output.scriptPubKey
|
||||
val signers = signersWithPubKeys.map(_._1)
|
||||
val unsignedInput = unsignedTx.inputs(inputIndex.toInt)
|
||||
@ -369,7 +369,7 @@ object MultiSigSigner extends MultiSigSigner
|
||||
|
||||
sealed abstract class P2WPKHSigner extends BitcoinSigner {
|
||||
override def sign(signers: Seq[Signer.Sign], output: TransactionOutput, unsignedTx: Transaction,
|
||||
inputIndex: UInt32, hashType: HashType): Either[TxSigComponent, TxBuilderError] = unsignedTx match {
|
||||
inputIndex: UInt32, hashType: HashType): Either[TxSigComponent, TxBuilderError] = unsignedTx match {
|
||||
case wtx: WitnessTransaction =>
|
||||
if (signers.size != 1) {
|
||||
Right(TxBuilderError.TooManySigners)
|
||||
|
@ -20,7 +20,7 @@ class RawMerkleBlockSerializerTest extends FlatSpec with MustMatchers {
|
||||
UInt32(2941790316L), UInt32(1626267458), UInt32(1688549344)), UInt32(1),
|
||||
PartialMerkleTree(
|
||||
Leaf(DoubleSha256Digest(
|
||||
"442abdc8e74ad35ebd9571f88fda91ff511dcda8d241a5aed52cea1e00d69e03")),
|
||||
"442abdc8e74ad35ebd9571f88fda91ff511dcda8d241a5aed52cea1e00d69e03")),
|
||||
UInt32(1),
|
||||
List(false, false, false, false, false, false, false, false),
|
||||
List(DoubleSha256Digest("442abdc8e74ad35ebd9571f88fda91ff511dcda8d241a5aed52cea1e00d69e03")))), List())
|
||||
@ -33,34 +33,34 @@ class RawMerkleBlockSerializerTest extends FlatSpec with MustMatchers {
|
||||
it must "not have any extra hashes left over when deserializing a previously valid partial merkle tree" in {
|
||||
val (merkleBlock, txIds) = (
|
||||
MerkleBlock(BlockHeader(
|
||||
UInt32(1626792925),
|
||||
DoubleSha256Digest("de2fc5fac498126f27c8adaa17aa86a1ef15d2b0adf5f2d2c056495bec17153f"),
|
||||
DoubleSha256Digest("f27404d701b9047cfcaa8d8454d2ecc12f4aa3e900ba8e5945bbb9289d67dd63"),
|
||||
UInt32(3098237133L), UInt32(359220269), UInt32(590323230)), UInt32(6),
|
||||
PartialMerkleTree(
|
||||
Node(
|
||||
DoubleSha256Digest("ed4f3665c72229886e4bdae876233892f8a7b85e5cee93da56be71d9056f6654"),
|
||||
Node(
|
||||
DoubleSha256Digest("2dc060204deff176f6e366319777d4db76546c17c07f23ebeece4bf0e66fd686"),
|
||||
UInt32(1626792925),
|
||||
DoubleSha256Digest("de2fc5fac498126f27c8adaa17aa86a1ef15d2b0adf5f2d2c056495bec17153f"),
|
||||
DoubleSha256Digest("f27404d701b9047cfcaa8d8454d2ecc12f4aa3e900ba8e5945bbb9289d67dd63"),
|
||||
UInt32(3098237133L), UInt32(359220269), UInt32(590323230)), UInt32(6),
|
||||
PartialMerkleTree(
|
||||
Node(
|
||||
DoubleSha256Digest("8023ea73c6c1e643d1604585abbfd997308a5759baa4d2d4a2ee876d71a5780f"),
|
||||
Leaf(DoubleSha256Digest("e4aeaf729035a7fb939e12c4f6a2072a9b2e7da784207ce7852d398593210a45")),
|
||||
Leaf(DoubleSha256Digest("010506d2103d0feb477224926eedaf3d7478fe3d93b54bd24e5eb2c0adc309b3"))),
|
||||
Node(
|
||||
DoubleSha256Digest("79a03d2d9f1c5c97772974c9ef9297e6e2bce0271ca95d40bb598c6156c3d6e0"),
|
||||
Leaf(DoubleSha256Digest("77352045b2995c9e0dfff9089e5563cd13914eb4b0723cdd54675c5c3f1c4f6a")),
|
||||
Leaf(DoubleSha256Digest("7ae10c30932c07e4ed25abab233565f9ab279eabbcd60e1bc028c6cdc400361b")))),
|
||||
Leaf(DoubleSha256Digest("8ca2e6b66c55fbb63cb7c9b5ccd19be508034eedcd8511d216b9fe93aafc2ceb"))),
|
||||
UInt32(6), List(true, true, true, false, true, true, false, true, false, false, false, false, false, false, false, false),
|
||||
DoubleSha256Digest("ed4f3665c72229886e4bdae876233892f8a7b85e5cee93da56be71d9056f6654"),
|
||||
Node(
|
||||
DoubleSha256Digest("2dc060204deff176f6e366319777d4db76546c17c07f23ebeece4bf0e66fd686"),
|
||||
Node(
|
||||
DoubleSha256Digest("8023ea73c6c1e643d1604585abbfd997308a5759baa4d2d4a2ee876d71a5780f"),
|
||||
Leaf(DoubleSha256Digest("e4aeaf729035a7fb939e12c4f6a2072a9b2e7da784207ce7852d398593210a45")),
|
||||
Leaf(DoubleSha256Digest("010506d2103d0feb477224926eedaf3d7478fe3d93b54bd24e5eb2c0adc309b3"))),
|
||||
Node(
|
||||
DoubleSha256Digest("79a03d2d9f1c5c97772974c9ef9297e6e2bce0271ca95d40bb598c6156c3d6e0"),
|
||||
Leaf(DoubleSha256Digest("77352045b2995c9e0dfff9089e5563cd13914eb4b0723cdd54675c5c3f1c4f6a")),
|
||||
Leaf(DoubleSha256Digest("7ae10c30932c07e4ed25abab233565f9ab279eabbcd60e1bc028c6cdc400361b")))),
|
||||
Leaf(DoubleSha256Digest("8ca2e6b66c55fbb63cb7c9b5ccd19be508034eedcd8511d216b9fe93aafc2ceb"))),
|
||||
UInt32(6), List(true, true, true, false, true, true, false, true, false, false, false, false, false, false, false, false),
|
||||
List(
|
||||
DoubleSha256Digest("e4aeaf729035a7fb939e12c4f6a2072a9b2e7da784207ce7852d398593210a45"),
|
||||
DoubleSha256Digest("010506d2103d0feb477224926eedaf3d7478fe3d93b54bd24e5eb2c0adc309b3"),
|
||||
DoubleSha256Digest("77352045b2995c9e0dfff9089e5563cd13914eb4b0723cdd54675c5c3f1c4f6a"),
|
||||
DoubleSha256Digest("7ae10c30932c07e4ed25abab233565f9ab279eabbcd60e1bc028c6cdc400361b"),
|
||||
DoubleSha256Digest("8ca2e6b66c55fbb63cb7c9b5ccd19be508034eedcd8511d216b9fe93aafc2ceb")))),
|
||||
List(
|
||||
DoubleSha256Digest("e4aeaf729035a7fb939e12c4f6a2072a9b2e7da784207ce7852d398593210a45"),
|
||||
DoubleSha256Digest("010506d2103d0feb477224926eedaf3d7478fe3d93b54bd24e5eb2c0adc309b3"),
|
||||
DoubleSha256Digest("77352045b2995c9e0dfff9089e5563cd13914eb4b0723cdd54675c5c3f1c4f6a"),
|
||||
DoubleSha256Digest("7ae10c30932c07e4ed25abab233565f9ab279eabbcd60e1bc028c6cdc400361b"),
|
||||
DoubleSha256Digest("8ca2e6b66c55fbb63cb7c9b5ccd19be508034eedcd8511d216b9fe93aafc2ceb")))),
|
||||
List(
|
||||
DoubleSha256Digest("010506d2103d0feb477224926eedaf3d7478fe3d93b54bd24e5eb2c0adc309b3"),
|
||||
DoubleSha256Digest("7ae10c30932c07e4ed25abab233565f9ab279eabbcd60e1bc028c6cdc400361b")))
|
||||
DoubleSha256Digest("7ae10c30932c07e4ed25abab233565f9ab279eabbcd60e1bc028c6cdc400361b")))
|
||||
|
||||
val hex = merkleBlock.hex
|
||||
val actualMerkleBlock = MerkleBlock(hex)
|
||||
|
Loading…
Reference in New Issue
Block a user