stdscript: Add v0 stake sub p2pkh support.
This adds support for detecting version 0 stake submission pay-to-pubkey-hash scripts as standard and extracting the associated public key hash. Full test coverage is included. This is part of a series of commits to fully implement the stdscript package.
This commit is contained in:
parent
bbaec90366
commit
08e2d88e8a
@ -81,6 +81,15 @@ const (
|
||||
// prunable.
|
||||
STNullData
|
||||
|
||||
// STStakeSubmissionPubKeyHash identifies a script that is only valid when
|
||||
// used as part of a ticket purchase transaction in the staking system and
|
||||
// is used for imposing voting rights.
|
||||
//
|
||||
// It imposes an encumbrance that requires a secp256k1 public key that
|
||||
// hashes to a specific value along with a valid ECDSA signature for that
|
||||
// public key.
|
||||
STStakeSubmissionPubKeyHash
|
||||
|
||||
// numScriptTypes is the maximum script type number used in tests. This
|
||||
// entry MUST be the last entry in the enum.
|
||||
numScriptTypes
|
||||
@ -99,6 +108,7 @@ var scriptTypeToName = []string{
|
||||
STScriptHash: "scripthash",
|
||||
STMultiSig: "multisig",
|
||||
STNullData: "nulldata",
|
||||
STStakeSubmissionPubKeyHash: "stakesubmission-pubkeyhash",
|
||||
}
|
||||
|
||||
// String returns the ScriptType as a human-readable name.
|
||||
@ -256,6 +266,20 @@ func IsNullDataScript(scriptVersion uint16, script []byte) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsStakeSubmissionPubKeyHashScript returns whether or not the passed script is
|
||||
// a standard stake submission pay-to-pubkey-hash script.
|
||||
//
|
||||
// NOTE: Version 0 scripts are the only currently supported version. It will
|
||||
// always return false for other script versions.
|
||||
func IsStakeSubmissionPubKeyHashScript(scriptVersion uint16, script []byte) bool {
|
||||
switch scriptVersion {
|
||||
case 0:
|
||||
return IsStakeSubmissionPubKeyHashScriptV0(script)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// DetermineScriptType returns the type of the script passed.
|
||||
//
|
||||
// NOTE: Version 0 scripts are the only currently supported version. It will
|
||||
|
||||
@ -26,6 +26,7 @@ func TestScriptTypeStringer(t *testing.T) {
|
||||
{STScriptHash, "scripthash"},
|
||||
{STMultiSig, "multisig"},
|
||||
{STNullData, "nulldata"},
|
||||
{STStakeSubmissionPubKeyHash, "stakesubmission-pubkeyhash"},
|
||||
{0xff, "invalid"},
|
||||
}
|
||||
|
||||
@ -143,6 +144,7 @@ func TestDetermineScriptType(t *testing.T) {
|
||||
testIsX(IsScriptHashScript, STScriptHash)
|
||||
testIsX(IsMultiSigScript, STMultiSig)
|
||||
testIsX(IsNullDataScript, STNullData)
|
||||
testIsX(IsStakeSubmissionPubKeyHashScript, STStakeSubmissionPubKeyHash)
|
||||
|
||||
// Ensure the special case of determining if a signature script appears
|
||||
// to be a signature script which consists of a pay-to-script-hash
|
||||
|
||||
@ -428,6 +428,39 @@ func IsNullDataScriptV0(script []byte) bool {
|
||||
isCanonicalPushV0(tokenizer.Opcode(), tokenizer.Data())
|
||||
}
|
||||
|
||||
// extractStakePubKeyHashV0 extracts the public key hash from the passed script
|
||||
// if it is a standard version 0 stake-tagged pay-to-pubkey-hash script with the
|
||||
// provided stake opcode. It will return nil otherwise.
|
||||
func extractStakePubKeyHashV0(script []byte, stakeOpcode byte) []byte {
|
||||
// A stake-tagged pay-to-pubkey-hash is of the form:
|
||||
// <stake opcode> <standard-pay-to-pubkey-hash script>
|
||||
|
||||
// The script can't possibly be a stake-tagged pay-to-pubkey-hash if it
|
||||
// doesn't start with the given stake opcode. Fail fast to avoid more work
|
||||
// below.
|
||||
if len(script) < 1 || script[0] != stakeOpcode {
|
||||
return nil
|
||||
}
|
||||
|
||||
return ExtractPubKeyHashV0(script[1:])
|
||||
}
|
||||
|
||||
// ExtractStakeSubmissionPubKeyHashV0 extracts the public key hash from
|
||||
// the passed script if it is a standard version 0 stake submission
|
||||
// pay-to-pubkey-hash script. It will return nil otherwise.
|
||||
func ExtractStakeSubmissionPubKeyHashV0(script []byte) []byte {
|
||||
// A stake submission pay-to-pubkey-hash script is of the form:
|
||||
// OP_SSTX <standard-pay-to-pubkey-hash script>
|
||||
const stakeOpcode = txscript.OP_SSTX
|
||||
return extractStakePubKeyHashV0(script, stakeOpcode)
|
||||
}
|
||||
|
||||
// IsStakeSubmissionPubKeyHashScriptV0 returns whether or not the passed script
|
||||
// is a standard version 0 stake submission pay-to-pubkey-hash script.
|
||||
func IsStakeSubmissionPubKeyHashScriptV0(script []byte) bool {
|
||||
return ExtractStakeSubmissionPubKeyHashV0(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.
|
||||
@ -453,6 +486,8 @@ func DetermineScriptTypeV0(script []byte) ScriptType {
|
||||
return STMultiSig
|
||||
case IsNullDataScriptV0(script):
|
||||
return STNullData
|
||||
case IsStakeSubmissionPubKeyHashScriptV0(script):
|
||||
return STStakeSubmissionPubKeyHash
|
||||
}
|
||||
|
||||
return STNonStandard
|
||||
|
||||
@ -520,6 +520,24 @@ var scriptV0Tests = func() []scriptTest {
|
||||
name: "v0 nulldata max standard push",
|
||||
script: p("RETURN PUSHDATA2 0x0001 0x01{256}"),
|
||||
wantType: STNullData,
|
||||
}, {
|
||||
// ---------------------------------------------------------------------
|
||||
// Negative stake submission P2PKH tests.
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
name: "almost v0 stake sub p2pkh-ecdsa-secp256k1 -- wrong hash length",
|
||||
script: p("SSTX DUP HASH160 DATA_21 0x00%s EQUALVERIFY CHECKSIG",
|
||||
h160CE),
|
||||
wantType: STNonStandard,
|
||||
}, {
|
||||
// ---------------------------------------------------------------------
|
||||
// Positive stake submission P2PKH tests.
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
name: "v0 stake submission p2pkh-ecdsa-secp256k1",
|
||||
script: p("SSTX DUP HASH160 DATA_20 0x%s EQUALVERIFY CHECKSIG", h160CE),
|
||||
wantType: STStakeSubmissionPubKeyHash,
|
||||
wantData: hexToBytes(h160CE),
|
||||
}}
|
||||
}()
|
||||
|
||||
@ -752,3 +770,24 @@ func TestMultiSigRedeemScriptFromScriptSigV0(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestExtractStakeSubmissionPubKeyHashV0 ensures that extracting a public key
|
||||
// hash from a version 0 stake submission pay-to-pubkey-hash script works as
|
||||
// intended for all of the version 0 test scripts.
|
||||
func TestExtractStakeSubmissionPubKeyHashV0(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 == STStakeSubmissionPubKeyHash {
|
||||
want = asByteSlice(t, test)
|
||||
}
|
||||
|
||||
got := ExtractStakeSubmissionPubKeyHashV0(test.script)
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("%q: unexpected pubkey hash -- got %x, want %x", test.name,
|
||||
got, want)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user