diff --git a/internal/staging/stdscript/script.go b/internal/staging/stdscript/script.go index a9c3da72..5b2b69d5 100644 --- a/internal/staging/stdscript/script.go +++ b/internal/staging/stdscript/script.go @@ -123,6 +123,14 @@ const ( // public key. STStakeRevocationPubKeyHash + // STStakeRevocationScriptHash identifies a script that is only valid when + // used as part of a revocation transaction in the staking system. + // + // It imposes an encumbrance that requires a script that hashes to a + // specific value along with all of the encumbrances that script itself + // imposes. The script is commonly referred to as a redeem script. + STStakeRevocationScriptHash + // numScriptTypes is the maximum script type number used in tests. This // entry MUST be the last entry in the enum. numScriptTypes @@ -146,6 +154,7 @@ var scriptTypeToName = []string{ STStakeGenPubKeyHash: "stakegen-pubkeyhash", STStakeGenScriptHash: "stakegen-scripthash", STStakeRevocationPubKeyHash: "stakerevoke-pubkeyhash", + STStakeRevocationScriptHash: "stakerevoke-scripthash", } // String returns the ScriptType as a human-readable name. @@ -373,6 +382,20 @@ func IsStakeRevocationPubKeyHashScript(scriptVersion uint16, script []byte) bool return false } +// IsStakeRevocationScriptHashScript returns whether or not the passed script is +// a standard stake revocation pay-to-script-hash script. +// +// NOTE: Version 0 scripts are the only currently supported version. It will +// always return false for other script versions. +func IsStakeRevocationScriptHashScript(scriptVersion uint16, script []byte) bool { + switch scriptVersion { + case 0: + return IsStakeRevocationScriptHashScriptV0(script) + } + + return false +} + // DetermineScriptType returns the type of the script passed. // // NOTE: Version 0 scripts are the only currently supported version. It will diff --git a/internal/staging/stdscript/script_test.go b/internal/staging/stdscript/script_test.go index 9cc527ae..eff06de8 100644 --- a/internal/staging/stdscript/script_test.go +++ b/internal/staging/stdscript/script_test.go @@ -31,6 +31,7 @@ func TestScriptTypeStringer(t *testing.T) { {STStakeGenPubKeyHash, "stakegen-pubkeyhash"}, {STStakeGenScriptHash, "stakegen-scripthash"}, {STStakeRevocationPubKeyHash, "stakerevoke-pubkeyhash"}, + {STStakeRevocationScriptHash, "stakerevoke-scripthash"}, {0xff, "invalid"}, } @@ -153,6 +154,7 @@ func TestDetermineScriptType(t *testing.T) { testIsX(IsStakeGenPubKeyHashScript, STStakeGenPubKeyHash) testIsX(IsStakeGenScriptHashScript, STStakeGenScriptHash) testIsX(IsStakeRevocationPubKeyHashScript, STStakeRevocationPubKeyHash) + testIsX(IsStakeRevocationScriptHashScript, STStakeRevocationScriptHash) // Ensure the special case of determining if a signature script appears // to be a signature script which consists of a pay-to-script-hash diff --git a/internal/staging/stdscript/scriptv0.go b/internal/staging/stdscript/scriptv0.go index c434a02f..8182fbfb 100644 --- a/internal/staging/stdscript/scriptv0.go +++ b/internal/staging/stdscript/scriptv0.go @@ -542,6 +542,22 @@ func IsStakeRevocationPubKeyHashScriptV0(script []byte) bool { return ExtractStakeRevocationPubKeyHashV0(script) != nil } +// ExtractStakeRevocationScriptHashV0 extracts the script hash from the +// passed script if it is a standard version 0 stake revocation +// pay-to-script-hash script. It will return nil otherwise. +func ExtractStakeRevocationScriptHashV0(script []byte) []byte { + // A stake revocation pay-to-script-hash script is of the form: + // OP_SSRTX + const stakeOpcode = txscript.OP_SSRTX + return extractStakeScriptHashV0(script, stakeOpcode) +} + +// IsStakeRevocationScriptHashScript returns whether or not the passed script is +// a standard version 0 stake revocation pay-to-script-hash script. +func IsStakeRevocationScriptHashScriptV0(script []byte) bool { + return ExtractStakeRevocationScriptHashV0(script) != nil +} + // DetermineScriptTypeV0 returns the type of the passed version 0 script from // the known standard types. This includes both types that are required by // consensus as well as those which are not. @@ -577,6 +593,8 @@ func DetermineScriptTypeV0(script []byte) ScriptType { return STStakeGenScriptHash case IsStakeRevocationPubKeyHashScriptV0(script): return STStakeRevocationPubKeyHash + case IsStakeRevocationScriptHashScriptV0(script): + return STStakeRevocationScriptHash } return STNonStandard diff --git a/internal/staging/stdscript/scriptv0_test.go b/internal/staging/stdscript/scriptv0_test.go index 13e9209f..664d5de0 100644 --- a/internal/staging/stdscript/scriptv0_test.go +++ b/internal/staging/stdscript/scriptv0_test.go @@ -610,6 +610,23 @@ var scriptV0Tests = func() []scriptTest { h160CE), wantType: STStakeRevocationPubKeyHash, wantData: hexToBytes(h160CE), + }, { + // --------------------------------------------------------------------- + // Negative stake submission revocation P2SH tests. + // --------------------------------------------------------------------- + + name: "almost v0 stake revoke p2sh -- wrong hash length", + script: p("SSRTX HASH160 DATA_21 0x00%s EQUAL", p2sh), + wantType: STNonStandard, + }, { + // --------------------------------------------------------------------- + // Positive stake submission revocation P2SH tests. + // --------------------------------------------------------------------- + + name: "v0 stake revoke p2sh", + script: p("SSRTX HASH160 DATA_20 0x%s EQUAL", p2sh), + wantType: STStakeRevocationScriptHash, + wantData: hexToBytes(p2sh), }} }() @@ -947,3 +964,24 @@ func TestExtractStakeRevocationPubKeyHashV0(t *testing.T) { } } } + +// TestExtractStakeRevocationScriptHashV0 ensures that extracting a script hash +// from a version 0 stake revocation pay-to-script-hash script works as intended +// for all of the version 0 test scripts. +func TestExtractStakeRevocationScriptHashV0(t *testing.T) { + for _, test := range scriptV0Tests { + // Determine the expected data based on the expected script type and + // data specified in the test. + var want []byte + if test.wantType == STStakeRevocationScriptHash { + want = asByteSlice(t, test) + } + + got := ExtractStakeRevocationScriptHashV0(test.script) + if !bytes.Equal(got, want) { + t.Errorf("%q: unexpected script hash -- got %x, want %x", test.name, + got, want) + continue + } + } +}