-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
make opcode internals public #5
Comments
The opcodes themselves are exported, so you can build custom scripts byte wise. I do agree that some type of "ScriptBuilder" interface might be a good addition for creating custom scripts, but I'm not really sure that simply exposing opcodemap/unparseScript is the best approach for that. It would most likely be the simplest approach however. @owainga: What are your thoughts on this one? In the mean time, while it's not the most user friendly thing, you can build a script by doing something similar to the following: package main
import(
"fmt"
"github.com/conformal/btcscript"
"github.com/conformal/btcutil"
)
func main() {
// This would obviously be a real script like a multi-sig or similar.
redeemScript := []byte{}
scriptHash := btcutil.Hash160(redeemScript)
// Construct the pay-to-script-hash script.
script := make([]byte, 23)
script[0] = btcscript.OP_HASH160
script[1] = btcscript.OP_DATA_20
copy(script[2:], scriptHash)
script[22] = btcscript.OP_EQUAL
// Ignoring the error here for demo purposes.
disasm, _ := btcscript.DisasmString(script)
fmt.Printf("Script: %x\n", script)
fmt.Printf("Script disassembly: %s\n", disasm)
} Which would produce the output:
|
@davecgh: Yes, the current interface is probably not the most interface for writing Script either :) btw, since we're building the script bytes by hand, shouldn't the OP_DATA_20 part be: script[0] = btcscript.OP_HASH160
script[1] = btcscript.OP_PUSHDATA1
script[2] = 20
copy(script[3:], scriptHash)
... ? |
No, OP_DATA_20 is the better choice. It is a single byte versus 2 bytes for the [OP_PUSHDATA1 20] pair. Also, I highly suspect that ultimately the standard transaction rules will be changed to only allow scripts which are canonical in regards to pushing data, meaning they only consume the least number of bytes possible to represent the data push. There has been some discussion amongst the community about it, and I, for one, believe it is something that really should happen. |
What would you think of an interface like the following? builder := btcscript.NewScriptBuilder()
builder.PushOp(btcscript.OP_HASH160).PushData(scriptHash).PushOp(btcscript.OP_EQUAL)
fmt.Printf("Script: %x\n", builder.Script()) |
Aaah, I didn't notice this fragment in scripts.h: if (opcode < OP_PUSHDATA1)
{
nSize = opcode;
} and GetOpName() doesn't know about (neither does the wiki), so I thought that the OP_DATA_XX was just something internal to btcscript :p About the interface: I actually also planned on doing a "builder" style interface, so it looks awesome to me :) ..Hash160().Data(scriptHash).Equal(). but either way is fine tbh. |
This commit adds a new ScriptBuilder interface that can be used to build custom scripts. It currently is fairly basic, but it allows you to push raw opcodes, ints, and data while respecting canonical encoding. These primitives are sufficient to build any script. This could be improved upon with quite a few things. One example would be functions for certain opcodes that take properly typed parameters to make it harder to create invalid scripts. For now though, it is already quite useful since it handles all of the opcode selection for canonical data pushes and integer encoding. The initial discussion took place in #5.
I've pushed the initial ScriptBuilder to master. |
Oh thanks! That's pretty handy! |
Hey there,
I'd like to construct some custom scripts (functionality it's similar to PayToScriptHashScript(), but the payload is different).
Sadly, opcodemap and unparseScript are private.
Any chance of making those public?
Thanks
The text was updated successfully, but these errors were encountered: