mirror of
https://github.com/btcsuite/btcd.git
synced 2025-02-24 06:47:59 +01:00
Merge pull request #1954 from guggero/script-builder-alloc
txscript: allow script builder capacity to be specified
This commit is contained in:
commit
38331963bd
2 changed files with 80 additions and 14 deletions
|
@ -13,11 +13,41 @@ const (
|
||||||
// defaultScriptAlloc is the default size used for the backing array
|
// defaultScriptAlloc is the default size used for the backing array
|
||||||
// for a script being built by the ScriptBuilder. The array will
|
// for a script being built by the ScriptBuilder. The array will
|
||||||
// dynamically grow as needed, but this figure is intended to provide
|
// dynamically grow as needed, but this figure is intended to provide
|
||||||
// enough space for vast majority of scripts without needing to grow the
|
// enough space for the vast majority of scripts without needing to grow
|
||||||
// backing array multiple times.
|
// the backing array multiple times. Can be overwritten with the
|
||||||
|
// WithScriptAllocSize functional option where expected script sizes are
|
||||||
|
// known.
|
||||||
defaultScriptAlloc = 500
|
defaultScriptAlloc = 500
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// scriptBuilderConfig is a configuration struct that can be used to modify the
|
||||||
|
// initialization of a ScriptBuilder.
|
||||||
|
type scriptBuilderConfig struct {
|
||||||
|
// allocSize specifies the initial size of the backing array for the
|
||||||
|
// script builder.
|
||||||
|
allocSize int
|
||||||
|
}
|
||||||
|
|
||||||
|
// defaultScriptBuilderConfig returns a new scriptBuilderConfig with the
|
||||||
|
// default values set.
|
||||||
|
func defaultScriptBuilderConfig() *scriptBuilderConfig {
|
||||||
|
return &scriptBuilderConfig{
|
||||||
|
allocSize: defaultScriptAlloc,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScriptBuilderOpt is a functional option type which is used to modify the
|
||||||
|
// initialization of a ScriptBuilder.
|
||||||
|
type ScriptBuilderOpt func(*scriptBuilderConfig)
|
||||||
|
|
||||||
|
// WithScriptAllocSize specifies the initial size of the backing array for the
|
||||||
|
// script builder.
|
||||||
|
func WithScriptAllocSize(size int) ScriptBuilderOpt {
|
||||||
|
return func(cfg *scriptBuilderConfig) {
|
||||||
|
cfg.allocSize = size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ErrScriptNotCanonical identifies a non-canonical script. The caller can use
|
// ErrScriptNotCanonical identifies a non-canonical script. The caller can use
|
||||||
// a type assertion to detect this error type.
|
// a type assertion to detect this error type.
|
||||||
type ErrScriptNotCanonical string
|
type ErrScriptNotCanonical string
|
||||||
|
@ -37,6 +67,7 @@ func (e ErrScriptNotCanonical) Error() string {
|
||||||
// For example, the following would build a 2-of-3 multisig script for usage in
|
// For example, the following would build a 2-of-3 multisig script for usage in
|
||||||
// a pay-to-script-hash (although in this situation MultiSigScript() would be a
|
// a pay-to-script-hash (although in this situation MultiSigScript() would be a
|
||||||
// better choice to generate the script):
|
// better choice to generate the script):
|
||||||
|
//
|
||||||
// builder := txscript.NewScriptBuilder()
|
// builder := txscript.NewScriptBuilder()
|
||||||
// builder.AddOp(txscript.OP_2).AddData(pubKey1).AddData(pubKey2)
|
// builder.AddOp(txscript.OP_2).AddData(pubKey1).AddData(pubKey2)
|
||||||
// builder.AddData(pubKey3).AddOp(txscript.OP_3)
|
// builder.AddData(pubKey3).AddOp(txscript.OP_3)
|
||||||
|
@ -267,8 +298,13 @@ func (b *ScriptBuilder) Script() ([]byte, error) {
|
||||||
|
|
||||||
// NewScriptBuilder returns a new instance of a script builder. See
|
// NewScriptBuilder returns a new instance of a script builder. See
|
||||||
// ScriptBuilder for details.
|
// ScriptBuilder for details.
|
||||||
func NewScriptBuilder() *ScriptBuilder {
|
func NewScriptBuilder(opts ...ScriptBuilderOpt) *ScriptBuilder {
|
||||||
|
cfg := defaultScriptBuilderConfig()
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(cfg)
|
||||||
|
}
|
||||||
|
|
||||||
return &ScriptBuilder{
|
return &ScriptBuilder{
|
||||||
script: make([]byte, 0, defaultScriptAlloc),
|
script: make([]byte, 0, cfg.allocSize),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,38 @@ package txscript
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TestScriptBuilderAlloc tests that the pre-allocation for a script via the
|
||||||
|
// NewScriptBuilder function works as expected.
|
||||||
|
func TestScriptBuilderAlloc(t *testing.T) {
|
||||||
|
// Using the default value, we should get a script with a capacity of
|
||||||
|
// 500 bytes, which is quite large for most scripts.
|
||||||
|
defaultBuilder := NewScriptBuilder()
|
||||||
|
require.EqualValues(t, defaultScriptAlloc, cap(defaultBuilder.script))
|
||||||
|
|
||||||
|
const allocSize = 23
|
||||||
|
builder := NewScriptBuilder(WithScriptAllocSize(allocSize))
|
||||||
|
|
||||||
|
// The initial capacity of the script should be set to the explicit
|
||||||
|
// value.
|
||||||
|
require.EqualValues(t, allocSize, cap(builder.script))
|
||||||
|
|
||||||
|
builder.AddOp(OP_HASH160)
|
||||||
|
builder.AddData(make([]byte, 20))
|
||||||
|
builder.AddOp(OP_EQUAL)
|
||||||
|
script, err := builder.Script()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Len(t, script, allocSize)
|
||||||
|
|
||||||
|
// The capacity shouldn't have changed, as the script should've fit just
|
||||||
|
// fine.
|
||||||
|
require.EqualValues(t, allocSize, cap(builder.script))
|
||||||
|
}
|
||||||
|
|
||||||
// TestScriptBuilderAddOp tests that pushing opcodes to a script via the
|
// TestScriptBuilderAddOp tests that pushing opcodes to a script via the
|
||||||
// ScriptBuilder API works as expected.
|
// ScriptBuilder API works as expected.
|
||||||
func TestScriptBuilderAddOp(t *testing.T) {
|
func TestScriptBuilderAddOp(t *testing.T) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue