mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-10-14 00:59:33 +00:00
Add script pubkey version to signature hash (#1360)
* Replace 0xffff with math.MaxUint16 on version checks * Add script version to the signature hash Co-authored-by: Ori Newman <orinewman1@gmail.com>
This commit is contained in:
parent
d8293ef635
commit
4577023e44
@ -4,6 +4,7 @@ import (
|
|||||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/utils/blockheader"
|
"github.com/kaspanet/kaspad/domain/consensus/utils/blockheader"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DomainBlockHeaderToDbBlockHeader converts BlockHeader to DbBlockHeader
|
// DomainBlockHeaderToDbBlockHeader converts BlockHeader to DbBlockHeader
|
||||||
@ -38,7 +39,7 @@ func DbBlockHeaderToDomainBlockHeader(dbBlockHeader *DbBlockHeader) (externalapi
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if dbBlockHeader.Version > 0xffff {
|
if dbBlockHeader.Version > math.MaxUint16 {
|
||||||
return nil, errors.Errorf("Invalid header version - bigger then uint16")
|
return nil, errors.Errorf("Invalid header version - bigger then uint16")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package serialization
|
|||||||
import (
|
import (
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DomainTransactionToDbTransaction converts DomainTransaction to DbTransaction
|
// DomainTransactionToDbTransaction converts DomainTransaction to DbTransaction
|
||||||
@ -73,7 +74,7 @@ func DbTransactionToDomainTransaction(dbTransaction *DbTransaction) (*externalap
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if dbTransaction.Version > 0xFFFF {
|
if dbTransaction.Version > math.MaxUint16 {
|
||||||
return nil, errors.Errorf("The transaction version is bigger then uint16.")
|
return nil, errors.Errorf("The transaction version is bigger then uint16.")
|
||||||
}
|
}
|
||||||
return &externalapi.DomainTransaction{
|
return &externalapi.DomainTransaction{
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/utils/utxo"
|
"github.com/kaspanet/kaspad/domain/consensus/utils/utxo"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ScriptPublicKeyToDBScriptPublicKey converts ScriptPublicKey to DBScriptPublicKey
|
// ScriptPublicKeyToDBScriptPublicKey converts ScriptPublicKey to DBScriptPublicKey
|
||||||
@ -13,7 +14,7 @@ func ScriptPublicKeyToDBScriptPublicKey(scriptPublicKey *externalapi.ScriptPubli
|
|||||||
|
|
||||||
// DBScriptPublicKeyToScriptPublicKey convert DbScriptPublicKey ro ScriptPublicKey
|
// DBScriptPublicKeyToScriptPublicKey convert DbScriptPublicKey ro ScriptPublicKey
|
||||||
func DBScriptPublicKeyToScriptPublicKey(dbScriptPublicKey *DbScriptPublicKey) (*externalapi.ScriptPublicKey, error) {
|
func DBScriptPublicKeyToScriptPublicKey(dbScriptPublicKey *DbScriptPublicKey) (*externalapi.ScriptPublicKey, error) {
|
||||||
if dbScriptPublicKey.Version > 0xFFFF {
|
if dbScriptPublicKey.Version > math.MaxUint16 {
|
||||||
return nil, errors.Errorf("The version on ScriptPublicKey is bigger then uint16.")
|
return nil, errors.Errorf("The version on ScriptPublicKey is bigger then uint16.")
|
||||||
}
|
}
|
||||||
return &externalapi.ScriptPublicKey{Script: dbScriptPublicKey.Script, Version: uint16(dbScriptPublicKey.Version)}, nil
|
return &externalapi.ScriptPublicKey{Script: dbScriptPublicKey.Script, Version: uint16(dbScriptPublicKey.Version)}, nil
|
||||||
|
@ -39,7 +39,7 @@ const (
|
|||||||
|
|
||||||
// Engine is the virtual machine that executes scripts.
|
// Engine is the virtual machine that executes scripts.
|
||||||
type Engine struct {
|
type Engine struct {
|
||||||
isKnownVersion bool
|
scriptVersion uint16
|
||||||
scripts [][]parsedOpcode
|
scripts [][]parsedOpcode
|
||||||
scriptIdx int
|
scriptIdx int
|
||||||
scriptOff int
|
scriptOff int
|
||||||
@ -315,7 +315,7 @@ func (vm *Engine) Step() (done bool, err error) {
|
|||||||
// Execute will execute all scripts in the script engine and return either nil
|
// Execute will execute all scripts in the script engine and return either nil
|
||||||
// for successful validation or an error if one occurred.
|
// for successful validation or an error if one occurred.
|
||||||
func (vm *Engine) Execute() (err error) {
|
func (vm *Engine) Execute() (err error) {
|
||||||
if !vm.isKnownVersion {
|
if vm.scriptVersion > constants.MaxScriptPublicKeyVersion {
|
||||||
log.Tracef("The version of the scriptPublicKey is higher than the known version - the Execute function returns true.")
|
log.Tracef("The version of the scriptPublicKey is higher than the known version - the Execute function returns true.")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -454,13 +454,11 @@ func NewEngine(scriptPubKey *externalapi.ScriptPublicKey, tx *externalapi.Domain
|
|||||||
return nil, scriptError(ErrEvalFalse,
|
return nil, scriptError(ErrEvalFalse,
|
||||||
"false stack entry at end of script execution")
|
"false stack entry at end of script execution")
|
||||||
}
|
}
|
||||||
vm := Engine{flags: flags, sigCache: sigCache}
|
vm := Engine{scriptVersion: scriptPubKey.Version, flags: flags, sigCache: sigCache}
|
||||||
|
|
||||||
if scriptPubKey.Version > constants.MaxScriptPublicKeyVersion {
|
if vm.scriptVersion > constants.MaxScriptPublicKeyVersion {
|
||||||
vm.isKnownVersion = false
|
|
||||||
return &vm, nil
|
return &vm, nil
|
||||||
}
|
}
|
||||||
vm.isKnownVersion = true
|
|
||||||
parsedScriptSig, err := parseScriptAndVerifySize(scriptSig)
|
parsedScriptSig, err := parseScriptAndVerifySize(scriptSig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -2034,7 +2034,7 @@ func opcodeCheckSig(op *parsedOpcode, vm *Engine) error {
|
|||||||
script := vm.currentScript()
|
script := vm.currentScript()
|
||||||
|
|
||||||
// Generate the signature hash based on the signature hash type.
|
// Generate the signature hash based on the signature hash type.
|
||||||
sigHash, err := calcSignatureHash(script, hashType, &vm.tx, vm.txIdx)
|
sigHash, err := calcSignatureHash(script, vm.scriptVersion, hashType, &vm.tx, vm.txIdx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
vm.dstack.PushBool(false)
|
vm.dstack.PushBool(false)
|
||||||
return nil
|
return nil
|
||||||
@ -2241,7 +2241,7 @@ func opcodeCheckMultiSig(op *parsedOpcode, vm *Engine) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate the signature hash based on the signature hash type.
|
// Generate the signature hash based on the signature hash type.
|
||||||
sigHash, err := calcSignatureHash(script, hashType, &vm.tx, vm.txIdx)
|
sigHash, err := calcSignatureHash(script, vm.scriptVersion, hashType, &vm.tx, vm.txIdx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ package txscript
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
|
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
|
||||||
|
|
||||||
@ -295,13 +296,13 @@ func CalcSignatureHash(script *externalapi.ScriptPublicKey, hashType SigHashType
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("cannot parse output script: %s", err)
|
return nil, errors.Errorf("cannot parse output script: %s", err)
|
||||||
}
|
}
|
||||||
return calcSignatureHash(parsedScript, hashType, tx, idx)
|
return calcSignatureHash(parsedScript, script.Version, hashType, tx, idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// calcSignatureHash will, given a script and hash type for the current script
|
// calcSignatureHash will, given a script and hash type for the current script
|
||||||
// engine instance, calculate the signature hash to be used for signing and
|
// engine instance, calculate the signature hash to be used for signing and
|
||||||
// verification.
|
// verification.
|
||||||
func calcSignatureHash(script []parsedOpcode, hashType SigHashType, tx *externalapi.DomainTransaction, idx int) (*externalapi.DomainHash, error) {
|
func calcSignatureHash(prevScriptPublicKey []parsedOpcode, scriptVersion uint16, hashType SigHashType, tx *externalapi.DomainTransaction, idx int) (*externalapi.DomainHash, error) {
|
||||||
// The SigHashSingle signature type signs only the corresponding input
|
// The SigHashSingle signature type signs only the corresponding input
|
||||||
// and output (the output with the same index number as the input).
|
// and output (the output with the same index number as the input).
|
||||||
//
|
//
|
||||||
@ -320,8 +321,10 @@ func calcSignatureHash(script []parsedOpcode, hashType SigHashType, tx *external
|
|||||||
if i == idx {
|
if i == idx {
|
||||||
// UnparseScript cannot fail here because removeOpcode
|
// UnparseScript cannot fail here because removeOpcode
|
||||||
// above only returns a valid script.
|
// above only returns a valid script.
|
||||||
sigScript, _ := unparseScript(script)
|
sigScript, _ := unparseScript(prevScriptPublicKey)
|
||||||
txCopy.Inputs[idx].SignatureScript = sigScript
|
var version [2]byte
|
||||||
|
binary.LittleEndian.PutUint16(version[:], scriptVersion)
|
||||||
|
txCopy.Inputs[idx].SignatureScript = append(version[:], sigScript...)
|
||||||
} else {
|
} else {
|
||||||
txCopy.Inputs[i].SignatureScript = nil
|
txCopy.Inputs[i].SignatureScript = nil
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
"github.com/kaspanet/kaspad/app/appmessage"
|
||||||
"github.com/kaspanet/kaspad/util/mstime"
|
"github.com/kaspanet/kaspad/util/mstime"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (x *BlockHeaderMessage) toAppMessage() (*appmessage.MsgBlockHeader, error) {
|
func (x *BlockHeaderMessage) toAppMessage() (*appmessage.MsgBlockHeader, error) {
|
||||||
@ -31,7 +32,7 @@ func (x *BlockHeaderMessage) toAppMessage() (*appmessage.MsgBlockHeader, error)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if x.Version > 0xffff {
|
if x.Version > math.MaxUint16 {
|
||||||
return nil, errors.Errorf("Invalid block header version - bigger then uint16")
|
return nil, errors.Errorf("Invalid block header version - bigger then uint16")
|
||||||
}
|
}
|
||||||
return &appmessage.MsgBlockHeader{
|
return &appmessage.MsgBlockHeader{
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
"github.com/kaspanet/kaspad/app/appmessage"
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (x *KaspadMessage_Transaction) toAppMessage() (appmessage.Message, error) {
|
func (x *KaspadMessage_Transaction) toAppMessage() (appmessage.Message, error) {
|
||||||
@ -30,7 +31,7 @@ func (x *TransactionMessage) toAppMessage() (appmessage.Message, error) {
|
|||||||
|
|
||||||
outputs := make([]*appmessage.TxOut, len(x.Outputs))
|
outputs := make([]*appmessage.TxOut, len(x.Outputs))
|
||||||
for i, protoOutput := range x.Outputs {
|
for i, protoOutput := range x.Outputs {
|
||||||
if protoOutput.ScriptPublicKey.Version > 0xFFFF {
|
if protoOutput.ScriptPublicKey.Version > math.MaxUint16 {
|
||||||
return nil, errors.Errorf("The version on ScriptPublicKey is bigger then uint16.")
|
return nil, errors.Errorf("The version on ScriptPublicKey is bigger then uint16.")
|
||||||
}
|
}
|
||||||
outputs[i] = &appmessage.TxOut{
|
outputs[i] = &appmessage.TxOut{
|
||||||
@ -55,7 +56,7 @@ func (x *TransactionMessage) toAppMessage() (appmessage.Message, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if x.Version > 0xffff {
|
if x.Version > math.MaxUint16 {
|
||||||
return nil, errors.Errorf("Invalid transaction version - bigger then uint16")
|
return nil, errors.Errorf("Invalid transaction version - bigger then uint16")
|
||||||
}
|
}
|
||||||
return &appmessage.MsgTx{
|
return &appmessage.MsgTx{
|
||||||
|
@ -3,6 +3,7 @@ package protowire
|
|||||||
import (
|
import (
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
"github.com/kaspanet/kaspad/app/appmessage"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (x *KaspadMessage_GetBlockRequest) toAppMessage() (appmessage.Message, error) {
|
func (x *KaspadMessage_GetBlockRequest) toAppMessage() (appmessage.Message, error) {
|
||||||
@ -72,7 +73,7 @@ func (x *BlockVerboseData) toAppMessage() (*appmessage.BlockVerboseData, error)
|
|||||||
transactionVerboseData[i] = appTransactionVerboseDatum
|
transactionVerboseData[i] = appTransactionVerboseDatum
|
||||||
}
|
}
|
||||||
|
|
||||||
if x.Version > 0xffff {
|
if x.Version > math.MaxUint16 {
|
||||||
return nil, errors.Errorf("Invalid block header version - bigger then uint16")
|
return nil, errors.Errorf("Invalid block header version - bigger then uint16")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +155,7 @@ func (x *TransactionVerboseData) toAppMessage() (*appmessage.TransactionVerboseD
|
|||||||
ScriptPubKey: scriptPubKey,
|
ScriptPubKey: scriptPubKey,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if x.Version > 0xffff {
|
if x.Version > math.MaxUint16 {
|
||||||
return nil, errors.Errorf("Invalid transaction version - bigger then uint16")
|
return nil, errors.Errorf("Invalid transaction version - bigger then uint16")
|
||||||
}
|
}
|
||||||
return &appmessage.TransactionVerboseData{
|
return &appmessage.TransactionVerboseData{
|
||||||
|
@ -3,6 +3,7 @@ package protowire
|
|||||||
import (
|
import (
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
"github.com/kaspanet/kaspad/app/appmessage"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (x *KaspadMessage_SubmitTransactionRequest) toAppMessage() (appmessage.Message, error) {
|
func (x *KaspadMessage_SubmitTransactionRequest) toAppMessage() (appmessage.Message, error) {
|
||||||
@ -71,7 +72,7 @@ func (x *RpcTransaction) toAppMessage() (*appmessage.RPCTransaction, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if x.Version > 0xffff {
|
if x.Version > math.MaxUint16 {
|
||||||
return nil, errors.Errorf("Invalid RPC txn version - bigger then uint16")
|
return nil, errors.Errorf("Invalid RPC txn version - bigger then uint16")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,7 +90,7 @@ func (x *RpcTransaction) toAppMessage() (*appmessage.RPCTransaction, error) {
|
|||||||
|
|
||||||
// ConvertFromAppMsgRPCScriptPubKeyToRPCScriptPubKey converts from RpcScriptPubKey to RPCScriptPublicKey.
|
// ConvertFromAppMsgRPCScriptPubKeyToRPCScriptPubKey converts from RpcScriptPubKey to RPCScriptPublicKey.
|
||||||
func ConvertFromAppMsgRPCScriptPubKeyToRPCScriptPubKey(toConvert *RpcScriptPublicKey) (*appmessage.RPCScriptPublicKey, error) {
|
func ConvertFromAppMsgRPCScriptPubKeyToRPCScriptPubKey(toConvert *RpcScriptPublicKey) (*appmessage.RPCScriptPublicKey, error) {
|
||||||
if toConvert.Version > 0xffff {
|
if toConvert.Version > math.MaxUint16 {
|
||||||
return nil, errors.Errorf("Invalid header version - bigger then uint16")
|
return nil, errors.Errorf("Invalid header version - bigger then uint16")
|
||||||
}
|
}
|
||||||
version := uint16(toConvert.Version)
|
version := uint16(toConvert.Version)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user