stdscript: Add ProvablyPruneableScriptV0.
This adds a function to generate a provably pruneable version 0 script that is considered standard since the equivalent variant of it is eventually going to be removed from txscript given it is a standardness construct as opposed to a consensus rule.
This commit is contained in:
parent
8bdccd19d1
commit
def72f32f3
@ -20,6 +20,11 @@ const (
|
||||
|
||||
// ErrPubKeyType is returned when a script contains invalid public keys.
|
||||
ErrPubKeyType = ErrorKind("ErrPubKeyType")
|
||||
|
||||
// ErrTooMuchNullData is returned when attempting to generate a
|
||||
// provably-pruneable script with data that exceeds the maximum allowed
|
||||
// length.
|
||||
ErrTooMuchNullData = ErrorKind("ErrTooMuchNullData")
|
||||
)
|
||||
|
||||
// Error satisfies the error interface and prints human-readable errors.
|
||||
|
||||
@ -19,6 +19,7 @@ func TestErrorKindStringer(t *testing.T) {
|
||||
{ErrUnsupportedScriptVersion, "ErrUnsupportedScriptVersion"},
|
||||
{ErrTooManyRequiredSigs, "ErrTooManyRequiredSigs"},
|
||||
{ErrPubKeyType, "ErrPubKeyType"},
|
||||
{ErrTooMuchNullData, "ErrTooMuchNullData"},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
|
||||
@ -722,6 +722,21 @@ func MultiSigScriptV0(threshold int, pubKeys ...[]byte) ([]byte, error) {
|
||||
return builder.Script()
|
||||
}
|
||||
|
||||
// ProvablyPruneableScriptV0 returns a valid version 0 provably-pruneable script
|
||||
// which consists of an OP_RETURN followed by the passed data. An Error with
|
||||
// kind ErrTooMuchNullData will be returned if the length of the passed data
|
||||
// exceeds MaxDataCarrierSizeV0.
|
||||
func ProvablyPruneableScriptV0(data []byte) ([]byte, error) {
|
||||
if len(data) > MaxDataCarrierSizeV0 {
|
||||
str := fmt.Sprintf("data size %d is larger than max allowed size %d",
|
||||
len(data), MaxDataCarrierSizeV0)
|
||||
return nil, makeError(ErrTooMuchNullData, str)
|
||||
}
|
||||
|
||||
builder := txscript.NewScriptBuilder()
|
||||
return builder.AddOp(txscript.OP_RETURN).AddData(data).Script()
|
||||
}
|
||||
|
||||
// AtomicSwapDataPushesV0 houses the data pushes found in hash-based atomic swap
|
||||
// contracts using version 0 scripts.
|
||||
type AtomicSwapDataPushesV0 struct {
|
||||
|
||||
@ -32,7 +32,7 @@ func hexToBytes(s string) []byte {
|
||||
// test global versus inside a specific test function scope since it spans
|
||||
// multiple tests and benchmarks.
|
||||
var scriptV0Tests = func() []scriptTest {
|
||||
// Convience function that combines fmt.Sprintf with mustParseShortForm
|
||||
// Convenience function that combines fmt.Sprintf with mustParseShortForm
|
||||
// to create more compact tests.
|
||||
p := func(format string, a ...interface{}) []byte {
|
||||
const scriptVersion = 0
|
||||
@ -1235,6 +1235,85 @@ func TestExtractTreasuryGenScriptHashV0(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestProvablyPruneableScriptV0 ensures generating a version 0
|
||||
// provably-pruneable nulldata script works as intended.
|
||||
func TestProvablyPruneableScriptV0(t *testing.T) {
|
||||
// Convenience function that closes over the script version and invokes
|
||||
// mustParseShortForm to create more compact tests.
|
||||
const scriptVersion = 0
|
||||
p := func(format string, a ...interface{}) []byte {
|
||||
return mustParseShortForm(scriptVersion, fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
data []byte
|
||||
expected []byte
|
||||
err error
|
||||
typ ScriptType
|
||||
}{{
|
||||
name: "small int",
|
||||
data: hexToBytes("01"),
|
||||
expected: p("RETURN 1"),
|
||||
err: nil,
|
||||
typ: STNullData,
|
||||
}, {
|
||||
name: "max small int",
|
||||
data: hexToBytes("10"),
|
||||
expected: p("RETURN 16"),
|
||||
err: nil,
|
||||
typ: STNullData,
|
||||
}, {
|
||||
name: "data of size before OP_PUSHDATA1 is needed",
|
||||
data: bytes.Repeat(hexToBytes("00"), 75),
|
||||
expected: p("RETURN DATA_75 0x00{75}"),
|
||||
err: nil,
|
||||
typ: STNullData,
|
||||
}, {
|
||||
name: "one less than max allowed size",
|
||||
data: bytes.Repeat(hexToBytes("00"), MaxDataCarrierSizeV0-1),
|
||||
expected: p("RETURN PUSHDATA1 0xff 0x00{255}"),
|
||||
err: nil,
|
||||
typ: STNullData,
|
||||
}, {
|
||||
name: "max allowed size",
|
||||
data: bytes.Repeat(hexToBytes("00"), MaxDataCarrierSizeV0),
|
||||
expected: p("RETURN PUSHDATA2 0x0001 0x00{256}"),
|
||||
err: nil,
|
||||
typ: STNullData,
|
||||
}, {
|
||||
name: "too big",
|
||||
data: bytes.Repeat(hexToBytes("00"), MaxDataCarrierSizeV0+1),
|
||||
expected: nil,
|
||||
err: ErrTooMuchNullData,
|
||||
typ: STNonStandard,
|
||||
}}
|
||||
|
||||
for _, test := range tests {
|
||||
script, err := ProvablyPruneableScriptV0(test.data)
|
||||
if !errors.Is(err, test.err) {
|
||||
t.Errorf("%q: unexpected error - got %v, want %v", test.name, err,
|
||||
test.err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Ensure the expected script was generated.
|
||||
if !bytes.Equal(script, test.expected) {
|
||||
t.Errorf("%q: unexpected script -- got: %x, want: %x", test.name,
|
||||
script, test.expected)
|
||||
continue
|
||||
}
|
||||
|
||||
// Ensure the script has the correct type.
|
||||
scriptType := DetermineScriptType(scriptVersion, script)
|
||||
if scriptType != test.typ {
|
||||
t.Errorf("%q: unexpected script type -- got: %v, want: %v",
|
||||
test.name, scriptType, test.typ)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// expectedAtomicSwapDataV0 is a convenience function that converts the passed
|
||||
// parameters into an expected version 0 atomic swap data pushes structure.
|
||||
func expectedAtomicSwapDataV0(recipientHash, refundHash, secretHash string, secretSize, lockTime int64) *AtomicSwapDataPushesV0 {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user