txscript: Add new flag ScriptVerifyLowS
The ScriptVerifyLowS flag defines that script signatures must comply with the DER format as well as have an S value less than or equal to the half order.
This commit is contained in:
parent
9523345814
commit
369b352452
3 changed files with 36 additions and 2 deletions
|
@ -701,6 +701,12 @@
|
|||
"DERSIG",
|
||||
"P2PK with multi-byte hashtype, with DERSIG"
|
||||
],
|
||||
[
|
||||
"0x48 0x304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef001",
|
||||
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
|
||||
"LOW_S",
|
||||
"P2PK with high S"
|
||||
],
|
||||
[
|
||||
"0x47 0x30440220745d63eb70d45652128b450aa5ca7d9b513439963f261cb1c40a60f0785e7ee402204877785b38945ca9dbec78e1c1d4dd12148cc25c868bd27480023b49ae0f310501",
|
||||
"0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
|
||||
|
|
|
@ -4579,6 +4579,8 @@ func parseScriptFlags(flagStr string) (ScriptFlags, error) {
|
|||
flags |= ScriptVerifyDERSignatures
|
||||
case "DISCOURAGE_UPGRADABLE_NOPS":
|
||||
flags |= ScriptDiscourageUpgradableNops
|
||||
case "LOW_S":
|
||||
flags |= ScriptVerifyLowS
|
||||
case "MINIMALDATA":
|
||||
flags |= ScriptVerifyMinimalData
|
||||
case "NONE":
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
|
@ -123,6 +124,11 @@ var (
|
|||
// is over the limit.
|
||||
ErrStackOverflow = errors.New("Stacks overflowed")
|
||||
|
||||
// ErrStackInvalidLowSSignature is returned when the ScriptVerifyLowS
|
||||
// flag is set and the script contains any signatures whose S values
|
||||
// are higher than the half order.
|
||||
ErrStackInvalidLowSSignature = errors.New("invalid low s signature")
|
||||
|
||||
// ErrStackInvalidPubKey is returned when the ScriptVerifyScriptEncoding
|
||||
// flag is set and the script contains invalid pubkeys.
|
||||
ErrStackInvalidPubKey = errors.New("invalid strict pubkey")
|
||||
|
@ -164,6 +170,9 @@ var ErrUnsupportedAddress = errors.New("unsupported address type")
|
|||
// This timestamp corresponds to Sun Apr 1 00:00:00 UTC 2012.
|
||||
var Bip16Activation = time.Unix(1333238400, 0)
|
||||
|
||||
// curve halforder, used to tame ECDSA malleability (see BIP0062)
|
||||
var halfOrder = new(big.Int).Rsh(btcec.S256().N, 1)
|
||||
|
||||
// SigHashType represents hash type bits at the end of a signature.
|
||||
type SigHashType byte
|
||||
|
||||
|
@ -232,7 +241,8 @@ type Script struct {
|
|||
discourageUpgradableNops bool // NOP1 to NOP10 are reserved for future soft-fork upgrades
|
||||
verifyStrictEncoding bool // verify strict encoding of signatures
|
||||
verifyCleanStack bool // verify stack is clean after script evaluation
|
||||
verifyDERSignatures bool // verify signatures compily with the DER
|
||||
verifyDERSignatures bool // verify signatures comply with the DER format
|
||||
verifyLowS bool // verify signatures comply with the DER format and have an S value <= halforder
|
||||
savedFirstStack [][]byte // stack from first script for bip16 scripts
|
||||
}
|
||||
|
||||
|
@ -388,7 +398,7 @@ func (s *Script) checkPubKeyEncoding(pubKey []byte) error {
|
|||
// checkSignatureEncoding returns whether or not the passed signature adheres to
|
||||
// the strict encoding requirements if enabled.
|
||||
func (s *Script) checkSignatureEncoding(sig []byte) error {
|
||||
if !s.verifyStrictEncoding && !s.verifyDERSignatures {
|
||||
if !s.verifyDERSignatures && !s.verifyLowS && !s.verifyStrictEncoding {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -470,6 +480,14 @@ func (s *Script) checkSignatureEncoding(sig []byte) error {
|
|||
return fmt.Errorf("malformed signature: invalid S value")
|
||||
}
|
||||
|
||||
// Verify the S value is <= halforder.
|
||||
if s.verifyLowS {
|
||||
sValue := new(big.Int).SetBytes(sig[rLen+6 : rLen+6+sLen])
|
||||
if sValue.Cmp(halfOrder) > 0 {
|
||||
return ErrStackInvalidLowSSignature
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -644,6 +662,11 @@ const (
|
|||
// to compily with the DER format.
|
||||
ScriptVerifyDERSignatures
|
||||
|
||||
// ScriptVerifyLowS defines that signtures are required to comply with
|
||||
// the DER format and whose S value is <= order / 2. This is rule 5
|
||||
// of BIP0062.
|
||||
ScriptVerifyLowS
|
||||
|
||||
// ScriptVerifyMinimalData defines that signatures must use the smallest
|
||||
// push operator. This is both rules 3 and 4 of BIP0062.
|
||||
ScriptVerifyMinimalData
|
||||
|
@ -737,6 +760,9 @@ func NewScript(scriptSig []byte, scriptPubKey []byte, txidx int, tx *wire.MsgTx,
|
|||
}
|
||||
m.verifyCleanStack = true
|
||||
}
|
||||
if flags&ScriptVerifyLowS == ScriptVerifyLowS {
|
||||
m.verifyLowS = true
|
||||
}
|
||||
|
||||
m.tx = *tx
|
||||
m.txidx = txidx
|
||||
|
|
Loading…
Reference in a new issue