mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2024-11-20 02:11:40 +01:00
implementing first parts of serializing a transaction to be signed by an ECKey
This commit is contained in:
parent
bf813287d4
commit
0f9a87f971
@ -26,7 +26,7 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper {
|
||||
* @param script
|
||||
* @return
|
||||
*/
|
||||
def serializeScriptCode(script : Seq[ScriptToken]) : String = removeOpCodeSeparators(script)
|
||||
def serializeScriptCode(script : Seq[ScriptToken]) : List[Byte] = removeOpCodeSeparators(script)
|
||||
|
||||
|
||||
def serializeInput(input : TransactionInput, nType : Int, nVersion : Int) : String = ???
|
||||
@ -56,11 +56,32 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper {
|
||||
}
|
||||
|
||||
def serialize(inputIndex : Int, nType : Int, script : ScriptPubKey, hashType : HashType) : String = {
|
||||
//remove signatures from all inputs because we cannot sign existing signatures
|
||||
// Clear input scripts in preparation for signing. If we're signing a fresh
|
||||
// transaction that step isn't very helpful, but it doesn't add much cost relative to the actual
|
||||
// EC math so we'll do it anyway.
|
||||
val txWithInputSigsRemoved = for {
|
||||
input <- spendingTransaction.inputs
|
||||
} yield input.factory(ScriptSignatureFactory.empty)
|
||||
???
|
||||
|
||||
|
||||
// This step has no purpose beyond being synchronized with Bitcoin Core's bugs. OP_CODESEPARATOR
|
||||
// is a legacy holdover from a previous, broken design of executing scripts that shipped in Bitcoin 0.1.
|
||||
// It was seriously flawed and would have let anyone take anyone elses money. Later versions switched to
|
||||
// the design we use today where scripts are executed independently but share a stack. This left the
|
||||
// OP_CODESEPARATOR instruction having no purpose as it was only meant to be used internally, not actually
|
||||
// ever put into scripts. Deleting OP_CODESEPARATOR is a step that should never be required but if we don't
|
||||
// do it, we could split off the main chain.
|
||||
val scriptWithOpCodeSeparatorsRemoved : List[Byte] = serializeScriptCode(script.asm)
|
||||
|
||||
val inputToSign = spendingTransaction.inputs(inputIndex)
|
||||
|
||||
// Set the input to the script of its output. Bitcoin Core does this but the step has no obvious purpose as
|
||||
// the signature covers the hash of the prevout transaction which obviously includes the output script
|
||||
// already. Perhaps it felt safer to him in some way, or is another leftover from how the code was written.
|
||||
val inputWithConnectedScript = inputToSign.factory(script)
|
||||
|
||||
//check the hash type of
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -68,12 +89,12 @@ trait TransactionSignatureSerializer extends RawBitcoinSerializerHelper {
|
||||
* format
|
||||
* @return
|
||||
*/
|
||||
def removeOpCodeSeparators(script : Seq[ScriptToken]) : String = {
|
||||
def removeOpCodeSeparators(script : Seq[ScriptToken]) : List[Byte] = {
|
||||
val scriptWithoutOpCodeSeparators : String = script.filterNot(_ == OP_CODESEPARATOR).map(_.hex).mkString
|
||||
val scriptWithoutOpCodeSeparatorSize = addPrecedingZero((scriptWithoutOpCodeSeparators.size / 2).toHexString)
|
||||
val expectedScript : ScriptPubKey = ScriptPubKeyFactory.factory(
|
||||
scriptWithoutOpCodeSeparatorSize + scriptWithoutOpCodeSeparators)
|
||||
expectedScript.hex
|
||||
expectedScript.bytes
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,13 +32,13 @@ trait BinaryTree[+T] {
|
||||
* @return
|
||||
*/
|
||||
def toSeqLeafValues : Seq[T] = {
|
||||
//TODO: Optimize this into a tailrec function
|
||||
def loop(tree : BinaryTree[T],accum : List[T]) : Seq[T] = tree match {
|
||||
case Leaf(x) => x :: accum
|
||||
case Empty => accum
|
||||
case Node(_,l,r) => loop(l,List()) ++ loop(r,List())
|
||||
@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 Node(_,l,r) => loop(l,accum,r :: remainder)
|
||||
}
|
||||
loop(this,List())
|
||||
loop(this,List(),List()).reverse
|
||||
}
|
||||
|
||||
|
||||
@ -80,7 +80,6 @@ trait BinaryTree[+T] {
|
||||
* Inserts a element into one of the two branches in a binary tree
|
||||
* if it cannot insert it because the branches are not empty
|
||||
* it throws a runtime exception
|
||||
* @param subTree
|
||||
* @param tree
|
||||
* @tparam T
|
||||
* @return
|
||||
@ -94,7 +93,7 @@ trait BinaryTree[+T] {
|
||||
* if it cannot insert it because the branches are not empty
|
||||
* it throws a runtime exception
|
||||
* @param subTree
|
||||
* @param tree
|
||||
* @param parentTree
|
||||
* @tparam T
|
||||
* @return
|
||||
*/
|
||||
@ -105,43 +104,48 @@ trait BinaryTree[+T] {
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes the subTree from the parentTree
|
||||
* @param subTree - the tree to be removed
|
||||
* @param parentTree - the tree of which the @subTree is being removed from
|
||||
* @tparam T
|
||||
* @return
|
||||
*/
|
||||
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 l : Leaf[T] => if (l == subTree) Empty else l
|
||||
case n : Node[T] => if (n == subTree) Empty
|
||||
else Node[T](n.value.get,remove(subTree)(n.left.getOrElse(Empty)),
|
||||
remove(subTree)(n.right.getOrElse(Empty)))
|
||||
case n : Node[T] =>
|
||||
if (n == subTree) Empty
|
||||
else Node[T](n.v,remove(subTree)(n.l), remove(subTree)(n.r))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces all instances of the original tree with the replacement tree
|
||||
* @param originalTree - the tree that needs to be replaced
|
||||
* @param replacement - the tree that is being put into the original tree
|
||||
* @param replacementTree - the tree that is being put into the original tree
|
||||
* @param parentTree - the tree that is being searched for instances to replace
|
||||
* @tparam T
|
||||
* @return
|
||||
*/
|
||||
def replace[T](originalTree : BinaryTree[T], replacement : BinaryTree[T])(implicit parentTree : BinaryTree[T] = this) : 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 => Empty
|
||||
case l : Leaf[T] => if (l == originalTree) replacement else l
|
||||
case n : Node[T] => if (n == originalTree) replacement else
|
||||
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,replacement)(n.l),
|
||||
replace(originalTree,replacement)(n.r))
|
||||
replace(originalTree,replacementTree)(n.l),
|
||||
replace(originalTree,replacementTree)(n.r))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
def toSeq : Seq[T] = {
|
||||
//TODO: Optimize this into a tailrec function
|
||||
//@tailrec
|
||||
|
Loading…
Reference in New Issue
Block a user