mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-01-18 21:34:39 +01:00
2022 06 13 taprootspk xonlypubkey (#4388)
* Implement XOnlyPubKey inside of TaprootScriptPubKey * Add ECPrivateKey.toXOnly * Address code review
This commit is contained in:
parent
7e2ecd9d6a
commit
ddbdde495d
@ -41,7 +41,7 @@ class ScriptPubKeyTest extends BitcoinSUnitTest {
|
||||
}
|
||||
|
||||
it must "construct valid witness spk v1 for taproot" in {
|
||||
val pubKey = CryptoGenerators.schnorrPublicKey.sample.get
|
||||
val pubKey = CryptoGenerators.xOnlyPubKey.sample.get
|
||||
val witSPKV1 = TaprootScriptPubKey.fromPubKey(pubKey)
|
||||
assert(witSPKV1.pubKey == pubKey)
|
||||
}
|
||||
|
@ -1347,7 +1347,7 @@ case class TaprootScriptPubKey(override val asm: Vector[ScriptToken])
|
||||
override def witnessProgram: Seq[ScriptToken] = asm.tail.tail
|
||||
override val scriptType: ScriptType = ScriptType.WITNESS_V1_TAPROOT
|
||||
|
||||
val pubKey: SchnorrPublicKey = SchnorrPublicKey.fromBytes(asm(2).bytes)
|
||||
val pubKey: XOnlyPubKey = XOnlyPubKey.fromBytes(asm(2).bytes)
|
||||
}
|
||||
|
||||
object TaprootScriptPubKey extends ScriptFactory[TaprootScriptPubKey] {
|
||||
@ -1358,16 +1358,20 @@ object TaprootScriptPubKey extends ScriptFactory[TaprootScriptPubKey] {
|
||||
s"Given asm was not a P2WSHWitnessSPKV0, got $asm")
|
||||
}
|
||||
|
||||
def apply(schnorrPubKey: SchnorrPublicKey): TaprootScriptPubKey = {
|
||||
fromPubKey(schnorrPubKey)
|
||||
def apply(xOnlyPubKey: XOnlyPubKey): TaprootScriptPubKey = {
|
||||
fromPubKey(xOnlyPubKey)
|
||||
}
|
||||
|
||||
def fromPubKey(schnorrPubKey: SchnorrPublicKey): TaprootScriptPubKey = {
|
||||
val pushOp = BitcoinScriptUtil.calculatePushOp(schnorrPubKey.bytes)
|
||||
val asm = OP_1 +: (pushOp ++ Vector(ScriptConstant(schnorrPubKey.bytes)))
|
||||
def fromPubKey(xOnlyPubKey: XOnlyPubKey): TaprootScriptPubKey = {
|
||||
val pushOp = BitcoinScriptUtil.calculatePushOp(xOnlyPubKey.bytes)
|
||||
val asm = OP_1 +: (pushOp ++ Vector(ScriptConstant(xOnlyPubKey.bytes)))
|
||||
fromAsm(asm)
|
||||
}
|
||||
|
||||
def fromPubKey(schnorrPublicKey: SchnorrPublicKey): TaprootScriptPubKey = {
|
||||
fromPubKey(schnorrPublicKey.toXOnly)
|
||||
}
|
||||
|
||||
def isValidAsm(asm: Seq[ScriptToken]): Boolean = {
|
||||
val asmBytes = BytesUtil.toByteVector(asm)
|
||||
asm.length == 3 &&
|
||||
@ -1375,7 +1379,7 @@ object TaprootScriptPubKey extends ScriptFactory[TaprootScriptPubKey] {
|
||||
WitnessScriptPubKey.isValidAsm(asm) &&
|
||||
asmBytes.size == 34 &&
|
||||
//have to make sure we have a valid xonly pubkey, not just 32 bytes
|
||||
SchnorrPublicKey.fromBytesT(asm(2).bytes).isSuccess
|
||||
XOnlyPubKey.fromBytesT(asm(2).bytes).isSuccess
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,6 +238,8 @@ case class ECPrivateKey(bytes: ByteVector)
|
||||
SchnorrPublicKey(publicKey.bytes)
|
||||
}
|
||||
|
||||
def toXOnly: XOnlyPubKey = schnorrPublicKey.toXOnly
|
||||
|
||||
def schnorrNonce: SchnorrNonce = {
|
||||
SchnorrNonce(publicKey.bytes)
|
||||
}
|
||||
|
@ -23,7 +23,8 @@ import org.bitcoins.crypto.{
|
||||
Sha256Digest,
|
||||
Sha256DigestBE,
|
||||
Sha256Hash160Digest,
|
||||
SipHashKey
|
||||
SipHashKey,
|
||||
XOnlyPubKey
|
||||
}
|
||||
import org.scalacheck.Gen
|
||||
import scodec.bits.{BitVector, ByteVector}
|
||||
@ -158,6 +159,8 @@ sealed abstract class CryptoGenerators {
|
||||
def schnorrPublicKey: Gen[SchnorrPublicKey] =
|
||||
publicKey.map(_.schnorrPublicKey)
|
||||
|
||||
def xOnlyPubKey: Gen[XOnlyPubKey] = publicKey.map(_.toXOnly)
|
||||
|
||||
/** Generate a sequence of private keys
|
||||
* @param num maximum number of keys to generate
|
||||
* @return
|
||||
|
@ -360,7 +360,7 @@ sealed abstract class ScriptGenerators {
|
||||
def witnessScriptPubKeyV1: Gen[(TaprootScriptPubKey, Seq[ECPrivateKey])] = {
|
||||
for {
|
||||
priv <- CryptoGenerators.privateKey
|
||||
pubKey = priv.schnorrPublicKey
|
||||
pubKey = priv.toXOnly
|
||||
} yield {
|
||||
(TaprootScriptPubKey.fromPubKey(pubKey), Vector(priv))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user