mirror of
https://github.com/kaspanet/kaspad.git
synced 2026-03-10 02:42:51 +00:00
[NOD-876] Replace ecc with go-secp256k1 for public keys (#670)
* Replace ecc with go-secp256k1 in txscript * Replace ecc with go-secp256k1 in util and cmd * Replace ecc.Multiset with secp256k1.MultiSet
This commit is contained in:
@@ -6,7 +6,6 @@ package blockdag
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/kaspanet/kaspad/ecc"
|
||||
"math"
|
||||
"sort"
|
||||
"sync"
|
||||
@@ -16,6 +15,7 @@ import (
|
||||
|
||||
"github.com/kaspanet/kaspad/util/subnetworkid"
|
||||
|
||||
"github.com/kaspanet/go-secp256k1"
|
||||
"github.com/kaspanet/kaspad/dagconfig"
|
||||
"github.com/kaspanet/kaspad/database"
|
||||
"github.com/kaspanet/kaspad/txscript"
|
||||
@@ -595,7 +595,7 @@ func (dag *BlockDAG) connectBlock(node *blockNode,
|
||||
}
|
||||
|
||||
// calcMultiset returns the multiset of the UTXO of the given block with the given transactions.
|
||||
func (node *blockNode) calcMultiset(dag *BlockDAG, transactions []*util.Tx, acceptanceData MultiBlockTxsAcceptanceData, selectedParentUTXO, pastUTXO UTXOSet) (*ecc.Multiset, error) {
|
||||
func (node *blockNode) calcMultiset(dag *BlockDAG, transactions []*util.Tx, acceptanceData MultiBlockTxsAcceptanceData, selectedParentUTXO, pastUTXO UTXOSet) (*secp256k1.MultiSet, error) {
|
||||
ms, err := node.pastUTXOMultiSet(dag, acceptanceData, selectedParentUTXO)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -615,10 +615,10 @@ func (node *blockNode) calcMultiset(dag *BlockDAG, transactions []*util.Tx, acce
|
||||
// parent, replaces all the selected parent outputs' blue score with
|
||||
// the block blue score and returns the result.
|
||||
func (node *blockNode) acceptedSelectedParentMultiset(dag *BlockDAG,
|
||||
acceptanceData MultiBlockTxsAcceptanceData) (*ecc.Multiset, error) {
|
||||
acceptanceData MultiBlockTxsAcceptanceData) (*secp256k1.MultiSet, error) {
|
||||
|
||||
if node.isGenesis() {
|
||||
return ecc.NewMultiset(ecc.S256()), nil
|
||||
return secp256k1.NewMultiset(), nil
|
||||
}
|
||||
|
||||
ms, err := dag.multisetStore.multisetByBlockNode(node.selectedParent)
|
||||
@@ -656,7 +656,7 @@ func (node *blockNode) acceptedSelectedParentMultiset(dag *BlockDAG,
|
||||
return ms, nil
|
||||
}
|
||||
|
||||
func (node *blockNode) pastUTXOMultiSet(dag *BlockDAG, acceptanceData MultiBlockTxsAcceptanceData, selectedParentUTXO UTXOSet) (*ecc.Multiset, error) {
|
||||
func (node *blockNode) pastUTXOMultiSet(dag *BlockDAG, acceptanceData MultiBlockTxsAcceptanceData, selectedParentUTXO UTXOSet) (*secp256k1.MultiSet, error) {
|
||||
ms, err := node.acceptedSelectedParentMultiset(dag, acceptanceData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -684,7 +684,7 @@ func (node *blockNode) pastUTXOMultiSet(dag *BlockDAG, acceptanceData MultiBlock
|
||||
return ms, nil
|
||||
}
|
||||
|
||||
func addTxToMultiset(ms *ecc.Multiset, tx *wire.MsgTx, pastUTXO UTXOSet, blockBlueScore uint64) (*ecc.Multiset, error) {
|
||||
func addTxToMultiset(ms *secp256k1.MultiSet, tx *wire.MsgTx, pastUTXO UTXOSet, blockBlueScore uint64) (*secp256k1.MultiSet, error) {
|
||||
isCoinbase := tx.IsCoinBase()
|
||||
if !isCoinbase {
|
||||
for _, txIn := range tx.TxIn {
|
||||
@@ -995,7 +995,7 @@ func (dag *BlockDAG) TxsAcceptedByBlockHash(blockHash *daghash.Hash) (MultiBlock
|
||||
// It returns the diff in the virtual block's UTXO set.
|
||||
//
|
||||
// This function MUST be called with the DAG state lock held (for writes).
|
||||
func (dag *BlockDAG) applyDAGChanges(node *blockNode, newBlockUTXO UTXOSet, newBlockMultiset *ecc.Multiset, selectedParentAnticone []*blockNode) (
|
||||
func (dag *BlockDAG) applyDAGChanges(node *blockNode, newBlockUTXO UTXOSet, newBlockMultiset *secp256k1.MultiSet, selectedParentAnticone []*blockNode) (
|
||||
virtualUTXODiff *UTXODiff, virtualTxsAcceptanceData MultiBlockTxsAcceptanceData,
|
||||
chainUpdates *chainUpdates, err error) {
|
||||
|
||||
@@ -1069,7 +1069,7 @@ func (node *blockNode) diffFromTxs(pastUTXO UTXOSet, transactions []*util.Tx) (*
|
||||
// to save extra traversals it returns the transactions acceptance data, the compactFeeData
|
||||
// for the new block and its multiset.
|
||||
func (node *blockNode) verifyAndBuildUTXO(dag *BlockDAG, transactions []*util.Tx, fastAdd bool) (
|
||||
newBlockUTXO UTXOSet, txsAcceptanceData MultiBlockTxsAcceptanceData, newBlockFeeData compactFeeData, multiset *ecc.Multiset, err error) {
|
||||
newBlockUTXO UTXOSet, txsAcceptanceData MultiBlockTxsAcceptanceData, newBlockFeeData compactFeeData, multiset *secp256k1.MultiSet, err error) {
|
||||
|
||||
pastUTXO, selectedParentUTXO, txsAcceptanceData, err := dag.pastUTXO(node)
|
||||
if err != nil {
|
||||
@@ -1100,7 +1100,7 @@ func (node *blockNode) verifyAndBuildUTXO(dag *BlockDAG, transactions []*util.Tx
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
|
||||
calculatedMultisetHash := multiset.Hash()
|
||||
calculatedMultisetHash := daghash.Hash(*multiset.Finalize())
|
||||
if !calculatedMultisetHash.IsEqual(node.utxoCommitment) {
|
||||
str := fmt.Sprintf("block %s UTXO commitment is invalid - block "+
|
||||
"header indicates %s, but calculated value is %s", node.hash,
|
||||
|
||||
@@ -3,9 +3,10 @@ package blockdag
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"github.com/kaspanet/kaspad/ecc"
|
||||
"github.com/kaspanet/go-secp256k1"
|
||||
"github.com/kaspanet/kaspad/txscript"
|
||||
"github.com/kaspanet/kaspad/util"
|
||||
"github.com/kaspanet/kaspad/util/daghash"
|
||||
"github.com/kaspanet/kaspad/wire"
|
||||
"time"
|
||||
)
|
||||
@@ -47,7 +48,7 @@ func (dag *BlockDAG) BlockForMining(transactions []*util.Tx) (*wire.MsgBlock, er
|
||||
ParentHashes: dag.TipHashes(),
|
||||
HashMerkleRoot: hashMerkleTree.Root(),
|
||||
AcceptedIDMerkleRoot: acceptedIDMerkleRoot,
|
||||
UTXOCommitment: multiset.Hash(),
|
||||
UTXOCommitment: (*daghash.Hash)(multiset.Finalize()),
|
||||
Timestamp: blockTimestamp,
|
||||
Bits: requiredDifficulty,
|
||||
}
|
||||
@@ -59,7 +60,7 @@ func (dag *BlockDAG) BlockForMining(transactions []*util.Tx) (*wire.MsgBlock, er
|
||||
// built on top of the current tips, with the given transactions.
|
||||
//
|
||||
// This function MUST be called with the DAG state lock held (for reads).
|
||||
func (dag *BlockDAG) NextBlockMultiset(transactions []*util.Tx) (*ecc.Multiset, error) {
|
||||
func (dag *BlockDAG) NextBlockMultiset(transactions []*util.Tx) (*secp256k1.MultiSet, error) {
|
||||
pastUTXO, selectedParentUTXO, txsAcceptanceData, err := dag.pastUTXO(&dag.virtual.blockNode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -2,27 +2,16 @@ package blockdag
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"github.com/kaspanet/kaspad/ecc"
|
||||
"github.com/kaspanet/go-secp256k1"
|
||||
"io"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
const multisetPointSize = 32
|
||||
|
||||
// serializeMultiset serializes an ECMH multiset. The serialization
|
||||
// uses the following format: <x (32 bytes)><y (32 bytes)>.
|
||||
func serializeMultiset(w io.Writer, ms *ecc.Multiset) error {
|
||||
x, y := ms.Point()
|
||||
xBytes := make([]byte, multisetPointSize)
|
||||
copy(xBytes, x.Bytes())
|
||||
yBytes := make([]byte, multisetPointSize)
|
||||
copy(yBytes, y.Bytes())
|
||||
|
||||
err := binary.Write(w, byteOrder, xBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = binary.Write(w, byteOrder, yBytes)
|
||||
// serializeMultiset serializes an ECMH multiset.
|
||||
func serializeMultiset(w io.Writer, ms *secp256k1.MultiSet) error {
|
||||
serialized := ms.Serialize()
|
||||
err := binary.Write(w, byteOrder, serialized)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -30,20 +19,11 @@ func serializeMultiset(w io.Writer, ms *ecc.Multiset) error {
|
||||
}
|
||||
|
||||
// deserializeMultiset deserializes an EMCH multiset.
|
||||
// See serializeMultiset for more details.
|
||||
func deserializeMultiset(r io.Reader) (*ecc.Multiset, error) {
|
||||
xBytes := make([]byte, multisetPointSize)
|
||||
yBytes := make([]byte, multisetPointSize)
|
||||
err := binary.Read(r, byteOrder, xBytes)
|
||||
func deserializeMultiset(r io.Reader) (*secp256k1.MultiSet, error) {
|
||||
serialized := &secp256k1.SerializedMultiSet{}
|
||||
err := binary.Read(r, byteOrder, serialized[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = binary.Read(r, byteOrder, yBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var x, y big.Int
|
||||
x.SetBytes(xBytes)
|
||||
y.SetBytes(yBytes)
|
||||
return ecc.NewMultisetFromPoint(ecc.S256(), &x, &y), nil
|
||||
return secp256k1.DeserializeMultiSet(serialized)
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ package blockdag
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/kaspanet/go-secp256k1"
|
||||
"github.com/kaspanet/kaspad/database"
|
||||
"github.com/kaspanet/kaspad/ecc"
|
||||
"github.com/kaspanet/kaspad/util/daghash"
|
||||
"github.com/kaspanet/kaspad/util/locks"
|
||||
"github.com/pkg/errors"
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
type multisetStore struct {
|
||||
dag *BlockDAG
|
||||
new map[daghash.Hash]struct{}
|
||||
loaded map[daghash.Hash]*ecc.Multiset
|
||||
loaded map[daghash.Hash]secp256k1.MultiSet
|
||||
mtx *locks.PriorityMutex
|
||||
}
|
||||
|
||||
@@ -20,12 +20,12 @@ func newMultisetStore(dag *BlockDAG) *multisetStore {
|
||||
return &multisetStore{
|
||||
dag: dag,
|
||||
new: make(map[daghash.Hash]struct{}),
|
||||
loaded: make(map[daghash.Hash]*ecc.Multiset),
|
||||
loaded: make(map[daghash.Hash]secp256k1.MultiSet),
|
||||
}
|
||||
}
|
||||
|
||||
func (store *multisetStore) setMultiset(node *blockNode, ms *ecc.Multiset) {
|
||||
store.loaded[*node.hash] = ms
|
||||
func (store *multisetStore) setMultiset(node *blockNode, ms *secp256k1.MultiSet) {
|
||||
store.loaded[*node.hash] = *ms
|
||||
store.addToNewBlocks(node.hash)
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ func multisetNotFoundError(blockHash *daghash.Hash) error {
|
||||
return errors.Errorf("Couldn't find multiset data for block %s", blockHash)
|
||||
}
|
||||
|
||||
func (store *multisetStore) multisetByBlockNode(node *blockNode) (*ecc.Multiset, error) {
|
||||
func (store *multisetStore) multisetByBlockNode(node *blockNode) (*secp256k1.MultiSet, error) {
|
||||
ms, exists := store.multisetByBlockHash(node.hash)
|
||||
if !exists {
|
||||
return nil, multisetNotFoundError(node.hash)
|
||||
@@ -45,9 +45,9 @@ func (store *multisetStore) multisetByBlockNode(node *blockNode) (*ecc.Multiset,
|
||||
return ms, nil
|
||||
}
|
||||
|
||||
func (store *multisetStore) multisetByBlockHash(hash *daghash.Hash) (*ecc.Multiset, bool) {
|
||||
func (store *multisetStore) multisetByBlockHash(hash *daghash.Hash) (*secp256k1.MultiSet, bool) {
|
||||
ms, ok := store.loaded[*hash]
|
||||
return ms, ok
|
||||
return &ms, ok
|
||||
}
|
||||
|
||||
// flushToDB writes all new multiset data to the database.
|
||||
@@ -66,7 +66,7 @@ func (store *multisetStore) flushToDB(dbTx database.Tx) error {
|
||||
return multisetNotFoundError(&hash)
|
||||
}
|
||||
|
||||
err := serializeMultiset(w, ms)
|
||||
err := serializeMultiset(w, &ms)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -97,7 +97,7 @@ func (store *multisetStore) init(dbTx database.Tx) error {
|
||||
return err
|
||||
}
|
||||
|
||||
store.loaded[*hash] = ms
|
||||
store.loaded[*hash] = *ms
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,24 +2,26 @@ package blockdag
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/kaspanet/kaspad/ecc"
|
||||
"github.com/kaspanet/go-secp256k1"
|
||||
"github.com/kaspanet/kaspad/wire"
|
||||
)
|
||||
|
||||
func addUTXOToMultiset(ms *ecc.Multiset, entry *UTXOEntry, outpoint *wire.Outpoint) (*ecc.Multiset, error) {
|
||||
func addUTXOToMultiset(ms *secp256k1.MultiSet, entry *UTXOEntry, outpoint *wire.Outpoint) (*secp256k1.MultiSet, error) {
|
||||
w := &bytes.Buffer{}
|
||||
err := serializeUTXO(w, entry, outpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ms.Add(w.Bytes()), nil
|
||||
ms.Add(w.Bytes())
|
||||
return ms, nil
|
||||
}
|
||||
|
||||
func removeUTXOFromMultiset(ms *ecc.Multiset, entry *UTXOEntry, outpoint *wire.Outpoint) (*ecc.Multiset, error) {
|
||||
func removeUTXOFromMultiset(ms *secp256k1.MultiSet, entry *UTXOEntry, outpoint *wire.Outpoint) (*secp256k1.MultiSet, error) {
|
||||
w := &bytes.Buffer{}
|
||||
err := serializeUTXO(w, entry, outpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ms.Remove(w.Bytes()), nil
|
||||
ms.Remove(w.Bytes())
|
||||
return ms, nil
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/kaspanet/kaspad/ecc"
|
||||
"github.com/kaspanet/go-secp256k1"
|
||||
"github.com/kaspanet/kaspad/wire"
|
||||
)
|
||||
|
||||
@@ -485,7 +485,7 @@ func NewFullUTXOSet() *FullUTXOSet {
|
||||
// newFullUTXOSetFromUTXOCollection converts a utxoCollection to a FullUTXOSet
|
||||
func newFullUTXOSetFromUTXOCollection(collection utxoCollection) (*FullUTXOSet, error) {
|
||||
var err error
|
||||
multiset := ecc.NewMultiset(ecc.S256())
|
||||
multiset := secp256k1.NewMultiset()
|
||||
for outpoint, utxoEntry := range collection {
|
||||
multiset, err = addUTXOToMultiset(multiset, utxoEntry, &outpoint)
|
||||
if err != nil {
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"github.com/kaspanet/kaspad/ecc"
|
||||
"github.com/kaspanet/go-secp256k1"
|
||||
"github.com/kaspanet/kaspad/txscript"
|
||||
"github.com/kaspanet/kaspad/util"
|
||||
"github.com/kaspanet/kaspad/wire"
|
||||
@@ -28,7 +28,11 @@ func main() {
|
||||
printErrorAndExit(err, "Failed to decode transaction")
|
||||
}
|
||||
|
||||
scriptPubKey, err := createScriptPubKey(privateKey.PubKey())
|
||||
pubkey, err := privateKey.SchnorrPublicKey()
|
||||
if err != nil {
|
||||
printErrorAndExit(err, "Failed to generate a public key")
|
||||
}
|
||||
scriptPubKey, err := createScriptPubKey(pubkey)
|
||||
if err != nil {
|
||||
printErrorAndExit(err, "Failed to create scriptPubKey")
|
||||
}
|
||||
@@ -46,10 +50,12 @@ func main() {
|
||||
fmt.Printf("Signed Transaction (hex): %s\n\n", serializedTransaction)
|
||||
}
|
||||
|
||||
func parsePrivateKey(privateKeyHex string) (*ecc.PrivateKey, error) {
|
||||
func parsePrivateKey(privateKeyHex string) (*secp256k1.PrivateKey, error) {
|
||||
privateKeyBytes, err := hex.DecodeString(privateKeyHex)
|
||||
privateKey, _ := ecc.PrivKeyFromBytes(ecc.S256(), privateKeyBytes)
|
||||
return privateKey, err
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("'%s' isn't a valid hex. err: '%s' ", privateKeyHex, err)
|
||||
}
|
||||
return secp256k1.DeserializePrivateKeyFromSlice(privateKeyBytes)
|
||||
}
|
||||
|
||||
func parseTransaction(transactionHex string) (*wire.MsgTx, error) {
|
||||
@@ -62,8 +68,12 @@ func parseTransaction(transactionHex string) (*wire.MsgTx, error) {
|
||||
return &transaction, err
|
||||
}
|
||||
|
||||
func createScriptPubKey(publicKey *ecc.PublicKey) ([]byte, error) {
|
||||
p2pkhAddress, err := util.NewAddressPubKeyHashFromPublicKey(publicKey.SerializeCompressed(), ActiveConfig().NetParams().Prefix)
|
||||
func createScriptPubKey(publicKey *secp256k1.SchnorrPublicKey) ([]byte, error) {
|
||||
serializedKey, err := publicKey.SerializeCompressed()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p2pkhAddress, err := util.NewAddressPubKeyHashFromPublicKey(serializedKey, ActiveConfig().NetParams().Prefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -71,7 +81,7 @@ func createScriptPubKey(publicKey *ecc.PublicKey) ([]byte, error) {
|
||||
return scriptPubKey, err
|
||||
}
|
||||
|
||||
func signTransaction(transaction *wire.MsgTx, privateKey *ecc.PrivateKey, scriptPubKey []byte) error {
|
||||
func signTransaction(transaction *wire.MsgTx, privateKey *secp256k1.PrivateKey, scriptPubKey []byte) error {
|
||||
for i, transactionInput := range transaction.TxIn {
|
||||
signatureScript, err := txscript.SignatureScript(transaction, i, scriptPubKey, txscript.SigHashAll, privateKey, true)
|
||||
if err != nil {
|
||||
|
||||
6
go.mod
6
go.mod
@@ -7,15 +7,15 @@ require (
|
||||
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792
|
||||
github.com/btcsuite/winsvc v1.0.0
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/golang/groupcache v0.0.0-20191002201903-404acd9df4cc
|
||||
github.com/golang/protobuf v1.3.2 // indirect
|
||||
github.com/golang/snappy v0.0.1 // indirect
|
||||
github.com/jessevdk/go-flags v1.4.0
|
||||
github.com/jrick/logrotate v1.0.0
|
||||
github.com/kaspanet/go-secp256k1 v0.0.0-20200326113007-add33b62838a
|
||||
github.com/kr/pretty v0.1.0 // indirect
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/syndtr/goleveldb v1.0.0
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 // indirect
|
||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59
|
||||
golang.org/x/sys v0.0.0-20190426135247-a129542de9ae // indirect
|
||||
golang.org/x/text v0.3.2 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
||||
|
||||
12
go.sum
12
go.sum
@@ -8,19 +8,21 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/golang/groupcache v0.0.0-20191002201903-404acd9df4cc h1:55rEp52jU6bkyslZ1+C/7NGfpQsEc6pxGLAGDOctqbw=
|
||||
github.com/golang/groupcache v0.0.0-20191002201903-404acd9df4cc/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI=
|
||||
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
||||
github.com/kaspanet/go-secp256k1 v0.0.0-20200326113007-add33b62838a h1:/7JHxqxFvfuUr+u8k8kZ4R8Gjyb0TZnvYXrMyGjEAN0=
|
||||
github.com/kaspanet/go-secp256k1 v0.0.0-20200326113007-add33b62838a/go.mod h1:W9OcWBKzH8P/PN2WAUn9k2YmZG/Uc660WAL1NTS3G3M=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
@@ -39,11 +41,15 @@ github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpP
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM=
|
||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -53,6 +59,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20200228224639-71482053b885/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
@@ -109,7 +109,7 @@ func PrepareBlockForTest(dag *blockdag.BlockDAG, params *dagconfig.Params, paren
|
||||
return nil, err
|
||||
}
|
||||
|
||||
template.Block.Header.UTXOCommitment = ms.Hash()
|
||||
template.Block.Header.UTXOCommitment = (*daghash.Hash)(ms.Finalize())
|
||||
}
|
||||
return template.Block, nil
|
||||
}
|
||||
|
||||
@@ -10,11 +10,11 @@ import (
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"github.com/kaspanet/go-secp256k1"
|
||||
"hash"
|
||||
|
||||
"golang.org/x/crypto/ripemd160"
|
||||
|
||||
"github.com/kaspanet/kaspad/ecc"
|
||||
"github.com/kaspanet/kaspad/util/daghash"
|
||||
"github.com/kaspanet/kaspad/wire"
|
||||
)
|
||||
@@ -2033,36 +2033,34 @@ func opcodeCheckSig(op *parsedOpcode, vm *Engine) error {
|
||||
script := vm.currentScript()
|
||||
|
||||
// Generate the signature hash based on the signature hash type.
|
||||
hash, err := calcSignatureHash(script, hashType, &vm.tx, vm.txIdx)
|
||||
sigHash, err := calcSignatureHash(script, hashType, &vm.tx, vm.txIdx)
|
||||
if err != nil {
|
||||
vm.dstack.PushBool(false)
|
||||
return nil
|
||||
}
|
||||
|
||||
pubKey, err := ecc.ParsePubKey(pkBytes, ecc.S256())
|
||||
pubKey, err := secp256k1.DeserializeSchnorrPubKey(pkBytes)
|
||||
if err != nil {
|
||||
vm.dstack.PushBool(false)
|
||||
return nil
|
||||
}
|
||||
|
||||
signature, err := ecc.ParseSignature(sigBytes)
|
||||
signature, err := secp256k1.DeserializeSchnorrSignatureFromSlice(sigBytes)
|
||||
if err != nil {
|
||||
vm.dstack.PushBool(false)
|
||||
return nil
|
||||
}
|
||||
|
||||
var valid bool
|
||||
secpHash := secp256k1.Hash(*sigHash)
|
||||
if vm.sigCache != nil {
|
||||
var sigHash daghash.Hash
|
||||
copy(sigHash[:], hash)
|
||||
|
||||
valid = vm.sigCache.Exists(sigHash, signature, pubKey)
|
||||
if !valid && signature.Verify(hash, pubKey) {
|
||||
vm.sigCache.Add(sigHash, signature, pubKey)
|
||||
valid = vm.sigCache.Exists(secpHash, signature, pubKey)
|
||||
if !valid && pubKey.SchnorrVerify(&secpHash, signature) {
|
||||
vm.sigCache.Add(secpHash, signature, pubKey)
|
||||
valid = true
|
||||
}
|
||||
} else {
|
||||
valid = signature.Verify(hash, pubKey)
|
||||
valid = pubKey.SchnorrVerify(&secpHash, signature)
|
||||
}
|
||||
|
||||
if !valid && len(sigBytes) > 0 {
|
||||
@@ -2092,7 +2090,7 @@ func opcodeCheckSigVerify(op *parsedOpcode, vm *Engine) error {
|
||||
// the same signature multiple times when verifying a multisig.
|
||||
type parsedSigInfo struct {
|
||||
signature []byte
|
||||
parsedSignature *ecc.Signature
|
||||
parsedSignature *secp256k1.SchnorrSignature
|
||||
parsed bool
|
||||
}
|
||||
|
||||
@@ -2204,7 +2202,7 @@ func opcodeCheckMultiSig(op *parsedOpcode, vm *Engine) error {
|
||||
signature := rawSig[:len(rawSig)-1]
|
||||
|
||||
// Only parse and check the signature encoding once.
|
||||
var parsedSig *ecc.Signature
|
||||
var parsedSig *secp256k1.SchnorrSignature
|
||||
if !sigInfo.parsed {
|
||||
if err := vm.checkHashTypeEncoding(hashType); err != nil {
|
||||
return err
|
||||
@@ -2214,13 +2212,12 @@ func opcodeCheckMultiSig(op *parsedOpcode, vm *Engine) error {
|
||||
}
|
||||
|
||||
// Parse the signature.
|
||||
var err error
|
||||
parsedSig, err = ecc.ParseSignature(signature)
|
||||
|
||||
parsedSig, err = secp256k1.DeserializeSchnorrSignatureFromSlice(signature)
|
||||
sigInfo.parsed = true
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
sigInfo.parsedSignature = parsedSig
|
||||
} else {
|
||||
// Skip to the next pubkey if the signature is invalid.
|
||||
@@ -2237,29 +2234,28 @@ func opcodeCheckMultiSig(op *parsedOpcode, vm *Engine) error {
|
||||
}
|
||||
|
||||
// Parse the pubkey.
|
||||
parsedPubKey, err := ecc.ParsePubKey(pubKey, ecc.S256())
|
||||
parsedPubKey, err := secp256k1.DeserializeSchnorrPubKey(pubKey)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Generate the signature hash based on the signature hash type.
|
||||
hash, err := calcSignatureHash(script, hashType, &vm.tx, vm.txIdx)
|
||||
sigHash, err := calcSignatureHash(script, hashType, &vm.tx, vm.txIdx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
secpHash := secp256k1.Hash(*sigHash)
|
||||
var valid bool
|
||||
if vm.sigCache != nil {
|
||||
var sigHash daghash.Hash
|
||||
copy(sigHash[:], hash)
|
||||
|
||||
valid = vm.sigCache.Exists(sigHash, parsedSig, parsedPubKey)
|
||||
if !valid && parsedSig.Verify(hash, parsedPubKey) {
|
||||
vm.sigCache.Add(sigHash, parsedSig, parsedPubKey)
|
||||
valid = vm.sigCache.Exists(secpHash, parsedSig, parsedPubKey)
|
||||
if !valid && parsedPubKey.SchnorrVerify(&secpHash, parsedSig) {
|
||||
vm.sigCache.Add(secpHash, parsedSig, parsedPubKey)
|
||||
valid = true
|
||||
}
|
||||
} else {
|
||||
valid = parsedSig.Verify(hash, parsedPubKey)
|
||||
valid = parsedPubKey.SchnorrVerify(&secpHash, parsedSig)
|
||||
}
|
||||
|
||||
if valid {
|
||||
|
||||
@@ -285,7 +285,7 @@ func shallowCopyTx(tx *wire.MsgTx) wire.MsgTx {
|
||||
// CalcSignatureHash will, given a script and hash type for the current script
|
||||
// engine instance, calculate the signature hash to be used for signing and
|
||||
// verification.
|
||||
func CalcSignatureHash(script []byte, hashType SigHashType, tx *wire.MsgTx, idx int) ([]byte, error) {
|
||||
func CalcSignatureHash(script []byte, hashType SigHashType, tx *wire.MsgTx, idx int) (*daghash.Hash, error) {
|
||||
parsedScript, err := parseScript(script)
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("cannot parse output script: %s", err)
|
||||
@@ -296,7 +296,7 @@ func CalcSignatureHash(script []byte, hashType SigHashType, tx *wire.MsgTx, idx
|
||||
// calcSignatureHash will, given a script and hash type for the current script
|
||||
// engine instance, calculate the signature hash to be used for signing and
|
||||
// verification.
|
||||
func calcSignatureHash(script []parsedOpcode, hashType SigHashType, tx *wire.MsgTx, idx int) ([]byte, error) {
|
||||
func calcSignatureHash(script []parsedOpcode, hashType SigHashType, tx *wire.MsgTx, idx int) (*daghash.Hash, error) {
|
||||
// The SigHashSingle signature type signs only the corresponding input
|
||||
// and output (the output with the same index number as the input).
|
||||
//
|
||||
@@ -367,7 +367,8 @@ func calcSignatureHash(script []parsedOpcode, hashType SigHashType, tx *wire.Msg
|
||||
wbuf := bytes.NewBuffer(make([]byte, 0, txCopy.SerializeSize()+4))
|
||||
txCopy.Serialize(wbuf)
|
||||
binary.Write(wbuf, binary.LittleEndian, hashType)
|
||||
return daghash.DoubleHashB(wbuf.Bytes()), nil
|
||||
hash := daghash.DoubleHashH(wbuf.Bytes())
|
||||
return &hash, nil
|
||||
}
|
||||
|
||||
// asSmallInt returns the passed opcode, which must be true according to
|
||||
|
||||
@@ -5,10 +5,8 @@
|
||||
package txscript
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/go-secp256k1"
|
||||
"sync"
|
||||
|
||||
"github.com/kaspanet/kaspad/ecc"
|
||||
"github.com/kaspanet/kaspad/util/daghash"
|
||||
)
|
||||
|
||||
// sigCacheEntry represents an entry in the SigCache. Entries within the
|
||||
@@ -18,8 +16,8 @@ import (
|
||||
// match. In the occasion that two sigHashes collide, the newer sigHash will
|
||||
// simply overwrite the existing entry.
|
||||
type sigCacheEntry struct {
|
||||
sig *ecc.Signature
|
||||
pubKey *ecc.PublicKey
|
||||
sig *secp256k1.SchnorrSignature
|
||||
pubKey *secp256k1.SchnorrPublicKey
|
||||
}
|
||||
|
||||
// SigCache implements an ECDSA signature verification cache with a randomized
|
||||
@@ -34,7 +32,7 @@ type sigCacheEntry struct {
|
||||
// if they've already been seen and verified within the mempool.
|
||||
type SigCache struct {
|
||||
sync.RWMutex
|
||||
validSigs map[daghash.Hash]sigCacheEntry
|
||||
validSigs map[secp256k1.Hash]sigCacheEntry
|
||||
maxEntries uint
|
||||
}
|
||||
|
||||
@@ -45,7 +43,7 @@ type SigCache struct {
|
||||
// cache to exceed the max.
|
||||
func NewSigCache(maxEntries uint) *SigCache {
|
||||
return &SigCache{
|
||||
validSigs: make(map[daghash.Hash]sigCacheEntry, maxEntries),
|
||||
validSigs: make(map[secp256k1.Hash]sigCacheEntry, maxEntries),
|
||||
maxEntries: maxEntries,
|
||||
}
|
||||
}
|
||||
@@ -55,7 +53,7 @@ func NewSigCache(maxEntries uint) *SigCache {
|
||||
//
|
||||
// NOTE: This function is safe for concurrent access. Readers won't be blocked
|
||||
// unless there exists a writer, adding an entry to the SigCache.
|
||||
func (s *SigCache) Exists(sigHash daghash.Hash, sig *ecc.Signature, pubKey *ecc.PublicKey) bool {
|
||||
func (s *SigCache) Exists(sigHash secp256k1.Hash, sig *secp256k1.SchnorrSignature, pubKey *secp256k1.SchnorrPublicKey) bool {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
entry, ok := s.validSigs[sigHash]
|
||||
@@ -70,7 +68,7 @@ func (s *SigCache) Exists(sigHash daghash.Hash, sig *ecc.Signature, pubKey *ecc.
|
||||
//
|
||||
// NOTE: This function is safe for concurrent access. Writers will block
|
||||
// simultaneous readers until function execution has concluded.
|
||||
func (s *SigCache) Add(sigHash daghash.Hash, sig *ecc.Signature, pubKey *ecc.PublicKey) {
|
||||
func (s *SigCache) Add(sigHash secp256k1.Hash, sig *secp256k1.SchnorrSignature, pubKey *secp256k1.SchnorrPublicKey) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
|
||||
@@ -6,32 +6,35 @@ package txscript
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"github.com/kaspanet/go-secp256k1"
|
||||
"testing"
|
||||
|
||||
"github.com/kaspanet/kaspad/ecc"
|
||||
"github.com/kaspanet/kaspad/util/daghash"
|
||||
)
|
||||
|
||||
// genRandomSig returns a random message, a signature of the message under the
|
||||
// public key and the public key. This function is used to generate randomized
|
||||
// test data.
|
||||
func genRandomSig() (*daghash.Hash, *ecc.Signature, *ecc.PublicKey, error) {
|
||||
privKey, err := ecc.NewPrivateKey(ecc.S256())
|
||||
func genRandomSig() (*secp256k1.Hash, *secp256k1.SchnorrSignature, *secp256k1.SchnorrPublicKey, error) {
|
||||
privKey, err := secp256k1.GeneratePrivateKey()
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
var msgHash daghash.Hash
|
||||
msgHash := &secp256k1.Hash{}
|
||||
if _, err := rand.Read(msgHash[:]); err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
sig, err := privKey.Sign(msgHash[:])
|
||||
sig, err := privKey.SchnorrSign(msgHash)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
return &msgHash, sig, privKey.PubKey(), nil
|
||||
pubkey, err := privKey.SchnorrPublicKey()
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
return msgHash, sig, pubkey, nil
|
||||
}
|
||||
|
||||
// TestSigCacheAddExists tests the ability to add, and later check the
|
||||
@@ -42,15 +45,16 @@ func TestSigCacheAddExists(t *testing.T) {
|
||||
// Generate a random sigCache entry triplet.
|
||||
msg1, sig1, key1, err := genRandomSig()
|
||||
if err != nil {
|
||||
t.Errorf("unable to generate random signature test data")
|
||||
t.Fatalf("unable to generate random signature test data")
|
||||
}
|
||||
|
||||
// Add the triplet to the signature cache.
|
||||
sigCache.Add(*msg1, sig1, key1)
|
||||
|
||||
// The previously added triplet should now be found within the sigcache.
|
||||
sig1Copy, _ := ecc.ParseSignature(sig1.Serialize())
|
||||
key1Copy, _ := ecc.ParsePubKey(key1.SerializeCompressed(), ecc.S256())
|
||||
sig1Copy := secp256k1.DeserializeSchnorrSignature(sig1.Serialize())
|
||||
key1Serialized, _ := key1.SerializeCompressed()
|
||||
key1Copy, _ := secp256k1.DeserializeSchnorrPubKey(key1Serialized)
|
||||
if !sigCache.Exists(*msg1, sig1Copy, key1Copy) {
|
||||
t.Errorf("previously added item not found in signature cache")
|
||||
}
|
||||
@@ -73,8 +77,9 @@ func TestSigCacheAddEvictEntry(t *testing.T) {
|
||||
|
||||
sigCache.Add(*msg, sig, key)
|
||||
|
||||
sigCopy, _ := ecc.ParseSignature(sig.Serialize())
|
||||
keyCopy, _ := ecc.ParsePubKey(key.SerializeCompressed(), ecc.S256())
|
||||
sigCopy := secp256k1.DeserializeSchnorrSignature(sig.Serialize())
|
||||
keySerialized, _ := key.SerializeCompressed()
|
||||
keyCopy, _ := secp256k1.DeserializeSchnorrPubKey(keySerialized)
|
||||
if !sigCache.Exists(*msg, sigCopy, keyCopy) {
|
||||
t.Errorf("previously added item not found in signature" +
|
||||
"cache")
|
||||
@@ -102,8 +107,9 @@ func TestSigCacheAddEvictEntry(t *testing.T) {
|
||||
}
|
||||
|
||||
// The entry added above should be found within the sigcache.
|
||||
sigNewCopy, _ := ecc.ParseSignature(sigNew.Serialize())
|
||||
keyNewCopy, _ := ecc.ParsePubKey(keyNew.SerializeCompressed(), ecc.S256())
|
||||
sigNewCopy := secp256k1.DeserializeSchnorrSignature(sigNew.Serialize())
|
||||
keyNewSerialized, _ := keyNew.SerializeCompressed()
|
||||
keyNewCopy, _ := secp256k1.DeserializeSchnorrPubKey(keyNewSerialized)
|
||||
if !sigCache.Exists(*msgNew, sigNewCopy, keyNewCopy) {
|
||||
t.Fatalf("previously added item not found in signature cache")
|
||||
}
|
||||
@@ -118,15 +124,16 @@ func TestSigCacheAddMaxEntriesZeroOrNegative(t *testing.T) {
|
||||
// Generate a random sigCache entry triplet.
|
||||
msg1, sig1, key1, err := genRandomSig()
|
||||
if err != nil {
|
||||
t.Errorf("unable to generate random signature test data")
|
||||
t.Fatalf("unable to generate random signature test data")
|
||||
}
|
||||
|
||||
// Add the triplet to the signature cache.
|
||||
sigCache.Add(*msg1, sig1, key1)
|
||||
|
||||
// The generated triplet should not be found.
|
||||
sig1Copy, _ := ecc.ParseSignature(sig1.Serialize())
|
||||
key1Copy, _ := ecc.ParsePubKey(key1.SerializeCompressed(), ecc.S256())
|
||||
sig1Copy := secp256k1.DeserializeSchnorrSignature(sig1.Serialize())
|
||||
key1Serialized, _ := key1.SerializeCompressed()
|
||||
key1Copy, _ := secp256k1.DeserializeSchnorrPubKey(key1Serialized)
|
||||
if sigCache.Exists(*msg1, sig1Copy, key1Copy) {
|
||||
t.Errorf("previously added signature found in sigcache, but" +
|
||||
"shouldn't have been")
|
||||
|
||||
@@ -5,29 +5,30 @@
|
||||
package txscript
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/go-secp256k1"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/kaspanet/kaspad/dagconfig"
|
||||
"github.com/kaspanet/kaspad/ecc"
|
||||
"github.com/kaspanet/kaspad/util"
|
||||
"github.com/kaspanet/kaspad/wire"
|
||||
)
|
||||
|
||||
// RawTxInSignature returns the serialized ECDSA signature for the input idx of
|
||||
// RawTxInSignature returns the serialized Schnorr signature for the input idx of
|
||||
// the given transaction, with hashType appended to it.
|
||||
func RawTxInSignature(tx *wire.MsgTx, idx int, script []byte,
|
||||
hashType SigHashType, key *ecc.PrivateKey) ([]byte, error) {
|
||||
hashType SigHashType, key *secp256k1.PrivateKey) ([]byte, error) {
|
||||
|
||||
hash, err := CalcSignatureHash(script, hashType, tx, idx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
signature, err := key.Sign(hash)
|
||||
secpHash := secp256k1.Hash(*hash)
|
||||
signature, err := key.SchnorrSign(&secpHash)
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("cannot sign tx input: %s", err)
|
||||
}
|
||||
|
||||
return append(signature.Serialize(), byte(hashType)), nil
|
||||
return append(signature.Serialize()[:], byte(hashType)), nil
|
||||
}
|
||||
|
||||
// SignatureScript creates an input signature script for tx to spend KAS sent
|
||||
@@ -38,18 +39,24 @@ func RawTxInSignature(tx *wire.MsgTx, idx int, script []byte,
|
||||
// as the idx'th input. privKey is serialized in either a compressed or
|
||||
// uncompressed format based on compress. This format must match the same format
|
||||
// used to generate the payment address, or the script validation will fail.
|
||||
func SignatureScript(tx *wire.MsgTx, idx int, script []byte, hashType SigHashType, privKey *ecc.PrivateKey, compress bool) ([]byte, error) {
|
||||
func SignatureScript(tx *wire.MsgTx, idx int, script []byte, hashType SigHashType, privKey *secp256k1.PrivateKey, compress bool) ([]byte, error) {
|
||||
sig, err := RawTxInSignature(tx, idx, script, hashType, privKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pk := (*ecc.PublicKey)(&privKey.PublicKey)
|
||||
pk, err := privKey.SchnorrPublicKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pkData []byte
|
||||
if compress {
|
||||
pkData = pk.SerializeCompressed()
|
||||
pkData, err = pk.SerializeCompressed()
|
||||
} else {
|
||||
pkData = pk.SerializeUncompressed()
|
||||
pkData, err = pk.SerializeUncompressed()
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewScriptBuilder().AddData(sig).AddData(pkData).Script()
|
||||
@@ -159,14 +166,14 @@ func mergeScripts(dagParams *dagconfig.Params, tx *wire.MsgTx, idx int,
|
||||
// KeyDB is an interface type provided to SignTxOutput, it encapsulates
|
||||
// any user state required to get the private keys for an address.
|
||||
type KeyDB interface {
|
||||
GetKey(util.Address) (*ecc.PrivateKey, bool, error)
|
||||
GetKey(util.Address) (*secp256k1.PrivateKey, bool, error)
|
||||
}
|
||||
|
||||
// KeyClosure implements KeyDB with a closure.
|
||||
type KeyClosure func(util.Address) (*ecc.PrivateKey, bool, error)
|
||||
type KeyClosure func(util.Address) (*secp256k1.PrivateKey, bool, error)
|
||||
|
||||
// GetKey implements KeyDB by returning the result of calling the closure.
|
||||
func (kc KeyClosure) GetKey(address util.Address) (*ecc.PrivateKey,
|
||||
func (kc KeyClosure) GetKey(address util.Address) (*secp256k1.PrivateKey,
|
||||
bool, error) {
|
||||
return kc(address)
|
||||
}
|
||||
|
||||
@@ -6,29 +6,29 @@ package txscript
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/kaspanet/go-secp256k1"
|
||||
"github.com/pkg/errors"
|
||||
"testing"
|
||||
|
||||
"github.com/kaspanet/kaspad/dagconfig"
|
||||
"github.com/kaspanet/kaspad/ecc"
|
||||
"github.com/kaspanet/kaspad/util"
|
||||
"github.com/kaspanet/kaspad/util/daghash"
|
||||
"github.com/kaspanet/kaspad/wire"
|
||||
)
|
||||
|
||||
type addressToKey struct {
|
||||
key *ecc.PrivateKey
|
||||
key *secp256k1.PrivateKey
|
||||
compressed bool
|
||||
}
|
||||
|
||||
func mkGetKey(keys map[string]addressToKey) KeyDB {
|
||||
if keys == nil {
|
||||
return KeyClosure(func(addr util.Address) (*ecc.PrivateKey,
|
||||
return KeyClosure(func(addr util.Address) (*secp256k1.PrivateKey,
|
||||
bool, error) {
|
||||
return nil, false, errors.New("nope")
|
||||
})
|
||||
}
|
||||
return KeyClosure(func(addr util.Address) (*ecc.PrivateKey,
|
||||
return KeyClosure(func(addr util.Address) (*secp256k1.PrivateKey,
|
||||
bool, error) {
|
||||
a2k, ok := keys[addr.EncodeAddress()]
|
||||
if !ok {
|
||||
@@ -139,17 +139,29 @@ func TestSignTxOutput(t *testing.T) {
|
||||
for _, hashType := range hashTypes {
|
||||
for i := range tx.TxIn {
|
||||
msg := fmt.Sprintf("%d:%d", hashType, i)
|
||||
key, err := ecc.NewPrivateKey(ecc.S256())
|
||||
key, err := secp256k1.GeneratePrivateKey()
|
||||
if err != nil {
|
||||
t.Errorf("failed to make privKey for %s: %v",
|
||||
t.Errorf("failed to make privKey for %s: %s",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pk := (*ecc.PublicKey)(&key.PublicKey).
|
||||
SerializeUncompressed()
|
||||
pubKey, err := key.SchnorrPublicKey()
|
||||
if err != nil {
|
||||
t.Errorf("failed to make a publickey for %s: %s",
|
||||
key, err)
|
||||
break
|
||||
}
|
||||
|
||||
uncompressedPubKey, err := pubKey.SerializeUncompressed()
|
||||
if err != nil {
|
||||
t.Errorf("failed to make a pubkey for %s: %s",
|
||||
key, err)
|
||||
break
|
||||
}
|
||||
|
||||
address, err := util.NewAddressPubKeyHash(
|
||||
util.Hash160(pk), util.Bech32PrefixKaspaTest)
|
||||
util.Hash160(uncompressedPubKey), util.Bech32PrefixKaspaTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make address for %s: %v",
|
||||
msg, err)
|
||||
@@ -176,17 +188,28 @@ func TestSignTxOutput(t *testing.T) {
|
||||
for _, hashType := range hashTypes {
|
||||
for i := range tx.TxIn {
|
||||
msg := fmt.Sprintf("%d:%d", hashType, i)
|
||||
key, err := ecc.NewPrivateKey(ecc.S256())
|
||||
key, err := secp256k1.GeneratePrivateKey()
|
||||
if err != nil {
|
||||
t.Errorf("failed to make privKey for %s: %v",
|
||||
t.Errorf("failed to make privKey for %s: %s",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pk := (*ecc.PublicKey)(&key.PublicKey).
|
||||
SerializeUncompressed()
|
||||
pubKey, err := key.SchnorrPublicKey()
|
||||
if err != nil {
|
||||
t.Errorf("failed to make a publickey for %s: %s",
|
||||
key, err)
|
||||
break
|
||||
}
|
||||
|
||||
uncompressedPubKey, err := pubKey.SerializeUncompressed()
|
||||
if err != nil {
|
||||
t.Errorf("failed to make a pubkey for %s: %s",
|
||||
key, err)
|
||||
break
|
||||
}
|
||||
address, err := util.NewAddressPubKeyHash(
|
||||
util.Hash160(pk), util.Bech32PrefixKaspaTest)
|
||||
util.Hash160(uncompressedPubKey), util.Bech32PrefixKaspaTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make address for %s: %v",
|
||||
msg, err)
|
||||
@@ -237,17 +260,29 @@ func TestSignTxOutput(t *testing.T) {
|
||||
for i := range tx.TxIn {
|
||||
msg := fmt.Sprintf("%d:%d", hashType, i)
|
||||
|
||||
key, err := ecc.NewPrivateKey(ecc.S256())
|
||||
key, err := secp256k1.GeneratePrivateKey()
|
||||
if err != nil {
|
||||
t.Errorf("failed to make privKey for %s: %v",
|
||||
t.Errorf("failed to make privKey for %s: %s",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pk := (*ecc.PublicKey)(&key.PublicKey).
|
||||
SerializeCompressed()
|
||||
pubKey, err := key.SchnorrPublicKey()
|
||||
if err != nil {
|
||||
t.Errorf("failed to make a publickey for %s: %s",
|
||||
key, err)
|
||||
break
|
||||
}
|
||||
|
||||
compressedPubKey, err := pubKey.SerializeCompressed()
|
||||
if err != nil {
|
||||
t.Errorf("failed to make a pubkey for %s: %s",
|
||||
key, err)
|
||||
break
|
||||
}
|
||||
|
||||
address, err := util.NewAddressPubKeyHash(
|
||||
util.Hash160(pk), util.Bech32PrefixKaspaTest)
|
||||
util.Hash160(compressedPubKey), util.Bech32PrefixKaspaTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make address for %s: %v",
|
||||
msg, err)
|
||||
@@ -275,17 +310,29 @@ func TestSignTxOutput(t *testing.T) {
|
||||
for i := range tx.TxIn {
|
||||
msg := fmt.Sprintf("%d:%d", hashType, i)
|
||||
|
||||
key, err := ecc.NewPrivateKey(ecc.S256())
|
||||
key, err := secp256k1.GeneratePrivateKey()
|
||||
if err != nil {
|
||||
t.Errorf("failed to make privKey for %s: %v",
|
||||
t.Errorf("failed to make privKey for %s: %s",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pk := (*ecc.PublicKey)(&key.PublicKey).
|
||||
SerializeCompressed()
|
||||
pubKey, err := key.SchnorrPublicKey()
|
||||
if err != nil {
|
||||
t.Errorf("failed to make a publickey for %s: %s",
|
||||
key, err)
|
||||
break
|
||||
}
|
||||
|
||||
compressedPubKey, err := pubKey.SerializeCompressed()
|
||||
if err != nil {
|
||||
t.Errorf("failed to make a pubkey for %s: %s",
|
||||
key, err)
|
||||
break
|
||||
}
|
||||
|
||||
address, err := util.NewAddressPubKeyHash(
|
||||
util.Hash160(pk), util.Bech32PrefixKaspaTest)
|
||||
util.Hash160(compressedPubKey), util.Bech32PrefixKaspaTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make address for %s: %v",
|
||||
msg, err)
|
||||
@@ -336,17 +383,29 @@ func TestSignTxOutput(t *testing.T) {
|
||||
for _, hashType := range hashTypes {
|
||||
for i := range tx.TxIn {
|
||||
msg := fmt.Sprintf("%d:%d", hashType, i)
|
||||
key, err := ecc.NewPrivateKey(ecc.S256())
|
||||
key, err := secp256k1.GeneratePrivateKey()
|
||||
if err != nil {
|
||||
t.Errorf("failed to make privKey for %s: %v",
|
||||
t.Errorf("failed to make privKey for %s: %s",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pk := (*ecc.PublicKey)(&key.PublicKey).
|
||||
SerializeUncompressed()
|
||||
pubKey, err := key.SchnorrPublicKey()
|
||||
if err != nil {
|
||||
t.Errorf("failed to make a publickey for %s: %s",
|
||||
key, err)
|
||||
break
|
||||
}
|
||||
|
||||
uncompressedPubKey, err := pubKey.SerializeUncompressed()
|
||||
if err != nil {
|
||||
t.Errorf("failed to make a pubkey for %s: %s",
|
||||
key, err)
|
||||
break
|
||||
}
|
||||
|
||||
address, err := util.NewAddressPubKeyHash(
|
||||
util.Hash160(pk), util.Bech32PrefixKaspaTest)
|
||||
util.Hash160(uncompressedPubKey), util.Bech32PrefixKaspaTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make address for %s: %v",
|
||||
msg, err)
|
||||
@@ -392,17 +451,29 @@ func TestSignTxOutput(t *testing.T) {
|
||||
for _, hashType := range hashTypes {
|
||||
for i := range tx.TxIn {
|
||||
msg := fmt.Sprintf("%d:%d", hashType, i)
|
||||
key, err := ecc.NewPrivateKey(ecc.S256())
|
||||
key, err := secp256k1.GeneratePrivateKey()
|
||||
if err != nil {
|
||||
t.Errorf("failed to make privKey for %s: %v",
|
||||
t.Errorf("failed to make privKey for %s: %s",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pk := (*ecc.PublicKey)(&key.PublicKey).
|
||||
SerializeUncompressed()
|
||||
pubKey, err := key.SchnorrPublicKey()
|
||||
if err != nil {
|
||||
t.Errorf("failed to make a publickey for %s: %s",
|
||||
key, err)
|
||||
break
|
||||
}
|
||||
|
||||
uncompressedPubKey, err := pubKey.SerializeUncompressed()
|
||||
if err != nil {
|
||||
t.Errorf("failed to make a pubkey for %s: %s",
|
||||
key, err)
|
||||
break
|
||||
}
|
||||
|
||||
address, err := util.NewAddressPubKeyHash(
|
||||
util.Hash160(pk), util.Bech32PrefixKaspaTest)
|
||||
util.Hash160(uncompressedPubKey), util.Bech32PrefixKaspaTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make address for %s: %v",
|
||||
msg, err)
|
||||
@@ -474,17 +545,29 @@ func TestSignTxOutput(t *testing.T) {
|
||||
for i := range tx.TxIn {
|
||||
msg := fmt.Sprintf("%d:%d", hashType, i)
|
||||
|
||||
key, err := ecc.NewPrivateKey(ecc.S256())
|
||||
key, err := secp256k1.GeneratePrivateKey()
|
||||
if err != nil {
|
||||
t.Errorf("failed to make privKey for %s: %v",
|
||||
t.Errorf("failed to make privKey for %s: %s",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pk := (*ecc.PublicKey)(&key.PublicKey).
|
||||
SerializeCompressed()
|
||||
pubKey, err := key.SchnorrPublicKey()
|
||||
if err != nil {
|
||||
t.Errorf("failed to make a publickey for %s: %s",
|
||||
key, err)
|
||||
break
|
||||
}
|
||||
|
||||
compressedPubKey, err := pubKey.SerializeCompressed()
|
||||
if err != nil {
|
||||
t.Errorf("failed to make a pubkey for %s: %s",
|
||||
key, err)
|
||||
break
|
||||
}
|
||||
|
||||
address, err := util.NewAddressPubKeyHash(
|
||||
util.Hash160(pk), util.Bech32PrefixKaspaTest)
|
||||
util.Hash160(compressedPubKey), util.Bech32PrefixKaspaTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make address for %s: %v",
|
||||
msg, err)
|
||||
@@ -530,17 +613,29 @@ func TestSignTxOutput(t *testing.T) {
|
||||
for i := range tx.TxIn {
|
||||
msg := fmt.Sprintf("%d:%d", hashType, i)
|
||||
|
||||
key, err := ecc.NewPrivateKey(ecc.S256())
|
||||
key, err := secp256k1.GeneratePrivateKey()
|
||||
if err != nil {
|
||||
t.Errorf("failed to make privKey for %s: %v",
|
||||
t.Errorf("failed to make privKey for %s: %s",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pk := (*ecc.PublicKey)(&key.PublicKey).
|
||||
SerializeCompressed()
|
||||
pubKey, err := key.SchnorrPublicKey()
|
||||
if err != nil {
|
||||
t.Errorf("failed to make a publickey for %s: %s",
|
||||
key, err)
|
||||
break
|
||||
}
|
||||
|
||||
compressedPubKey, err := pubKey.SerializeCompressed()
|
||||
if err != nil {
|
||||
t.Errorf("failed to make a pubkey for %s: %s",
|
||||
key, err)
|
||||
break
|
||||
}
|
||||
|
||||
address, err := util.NewAddressPubKeyHash(
|
||||
util.Hash160(pk), util.Bech32PrefixKaspaTest)
|
||||
util.Hash160(compressedPubKey), util.Bech32PrefixKaspaTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make address for %s: %v",
|
||||
msg, err)
|
||||
@@ -629,7 +724,7 @@ var coinbaseOutpoint = &wire.Outpoint{
|
||||
// Pregenerated private key, with associated public key and scriptPubKeys
|
||||
// for the uncompressed and compressed hash160.
|
||||
var (
|
||||
privKeyD = []byte{0x6b, 0x0f, 0xd8, 0xda, 0x54, 0x22, 0xd0, 0xb7,
|
||||
privKeyD = secp256k1.SerializedPrivateKey{0x6b, 0x0f, 0xd8, 0xda, 0x54, 0x22, 0xd0, 0xb7,
|
||||
0xb4, 0xfc, 0x4e, 0x55, 0xd4, 0x88, 0x42, 0xb3, 0xa1, 0x65,
|
||||
0xac, 0x70, 0x7f, 0x3d, 0xa4, 0x39, 0x5e, 0xcb, 0x3b, 0xb0,
|
||||
0xd6, 0x0e, 0x06, 0x92}
|
||||
@@ -864,7 +959,7 @@ var sigScriptTests = []tstSigScript{
|
||||
func TestSignatureScript(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
privKey, _ := ecc.PrivKeyFromBytes(ecc.S256(), privKeyD)
|
||||
privKey, _ := secp256k1.DeserializePrivateKey(&privKeyD)
|
||||
|
||||
nexttest:
|
||||
for i := range sigScriptTests {
|
||||
|
||||
@@ -221,8 +221,13 @@ func TestFilterInsertKey(t *testing.T) {
|
||||
}
|
||||
|
||||
f := bloom.NewFilter(2, 0, 0.001, wire.BloomUpdateAll)
|
||||
f.Add(wif.SerializePubKey())
|
||||
f.Add(util.Hash160(wif.SerializePubKey()))
|
||||
serializedPubKey, err := wif.SerializePubKey()
|
||||
if err != nil {
|
||||
t.Errorf("TestFilterInsertKey SerializePubKey failed: %v", err)
|
||||
return
|
||||
}
|
||||
f.Add(serializedPubKey)
|
||||
f.Add(util.Hash160(serializedPubKey))
|
||||
|
||||
want, err := hex.DecodeString("038fc16b080000000000000001")
|
||||
if err != nil {
|
||||
|
||||
32
util/wif.go
32
util/wif.go
@@ -6,7 +6,7 @@ package util
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/kaspanet/kaspad/ecc"
|
||||
"github.com/kaspanet/go-secp256k1"
|
||||
"github.com/kaspanet/kaspad/util/base58"
|
||||
"github.com/kaspanet/kaspad/util/daghash"
|
||||
"github.com/pkg/errors"
|
||||
@@ -30,7 +30,7 @@ const compressMagic byte = 0x01
|
||||
// by calling NewWIF.
|
||||
type WIF struct {
|
||||
// PrivKey is the private key being imported or exported.
|
||||
PrivKey *ecc.PrivateKey
|
||||
PrivKey *secp256k1.PrivateKey
|
||||
|
||||
// CompressPubKey specifies whether the address controlled by the
|
||||
// imported or exported private key was created by hashing a
|
||||
@@ -47,7 +47,7 @@ type WIF struct {
|
||||
// as a string encoded in the Wallet Import Format. The compress argument
|
||||
// specifies whether the address intended to be imported or exported was created
|
||||
// by serializing the public key compressed rather than uncompressed.
|
||||
func NewWIF(privKey *ecc.PrivateKey, privateKeyID byte, compress bool) (*WIF, error) {
|
||||
func NewWIF(privKey *secp256k1.PrivateKey, privateKeyID byte, compress bool) (*WIF, error) {
|
||||
return &WIF{privKey, compress, privateKeyID}, nil
|
||||
}
|
||||
|
||||
@@ -85,12 +85,12 @@ func DecodeWIF(wif string) (*WIF, error) {
|
||||
// Length of base58 decoded WIF must be 32 bytes + an optional 1 byte
|
||||
// (0x01) if compressed, plus 1 byte for netID + 4 bytes of checksum.
|
||||
switch decodedLen {
|
||||
case 1 + ecc.PrivKeyBytesLen + 1 + 4:
|
||||
case 1 + secp256k1.SerializedPrivateKeySize + 1 + 4:
|
||||
if decoded[33] != compressMagic {
|
||||
return nil, ErrMalformedPrivateKey
|
||||
}
|
||||
compress = true
|
||||
case 1 + ecc.PrivKeyBytesLen + 4:
|
||||
case 1 + secp256k1.SerializedPrivateKeySize + 4:
|
||||
compress = false
|
||||
default:
|
||||
return nil, ErrMalformedPrivateKey
|
||||
@@ -101,9 +101,9 @@ func DecodeWIF(wif string) (*WIF, error) {
|
||||
// private key.
|
||||
var tosum []byte
|
||||
if compress {
|
||||
tosum = decoded[:1+ecc.PrivKeyBytesLen+1]
|
||||
tosum = decoded[:1+secp256k1.SerializedPrivateKeySize+1]
|
||||
} else {
|
||||
tosum = decoded[:1+ecc.PrivKeyBytesLen]
|
||||
tosum = decoded[:1+secp256k1.SerializedPrivateKeySize]
|
||||
}
|
||||
cksum := daghash.DoubleHashB(tosum)[:4]
|
||||
if !bytes.Equal(cksum, decoded[decodedLen-4:]) {
|
||||
@@ -111,8 +111,11 @@ func DecodeWIF(wif string) (*WIF, error) {
|
||||
}
|
||||
|
||||
netID := decoded[0]
|
||||
privKeyBytes := decoded[1 : 1+ecc.PrivKeyBytesLen]
|
||||
privKey, _ := ecc.PrivKeyFromBytes(ecc.S256(), privKeyBytes)
|
||||
privKeyBytes := decoded[1 : 1+secp256k1.SerializedPrivateKeySize]
|
||||
privKey, err := secp256k1.DeserializePrivateKeyFromSlice(privKeyBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &WIF{privKey, compress, netID}, nil
|
||||
}
|
||||
|
||||
@@ -124,7 +127,7 @@ func (w *WIF) String() string {
|
||||
// is one byte for the network, 32 bytes of private key, possibly one
|
||||
// extra byte if the pubkey is to be compressed, and finally four
|
||||
// bytes of checksum.
|
||||
encodeLen := 1 + ecc.PrivKeyBytesLen + 4
|
||||
encodeLen := 1 + secp256k1.SerializedPrivateKeySize + 4
|
||||
if w.CompressPubKey {
|
||||
encodeLen++
|
||||
}
|
||||
@@ -133,7 +136,7 @@ func (w *WIF) String() string {
|
||||
a = append(a, w.netID)
|
||||
// Pad and append bytes manually, instead of using Serialize, to
|
||||
// avoid another call to make.
|
||||
a = paddedAppend(ecc.PrivKeyBytesLen, a, w.PrivKey.D.Bytes())
|
||||
a = paddedAppend(secp256k1.SerializedPrivateKeySize, a, w.PrivKey.Serialize()[:])
|
||||
if w.CompressPubKey {
|
||||
a = append(a, compressMagic)
|
||||
}
|
||||
@@ -145,8 +148,11 @@ func (w *WIF) String() string {
|
||||
// SerializePubKey serializes the associated public key of the imported or
|
||||
// exported private key in either a compressed or uncompressed format. The
|
||||
// serialization format chosen depends on the value of w.CompressPubKey.
|
||||
func (w *WIF) SerializePubKey() []byte {
|
||||
pk := (*ecc.PublicKey)(&w.PrivKey.PublicKey)
|
||||
func (w *WIF) SerializePubKey() ([]byte, error) {
|
||||
pk, err := w.PrivKey.SchnorrPublicKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if w.CompressPubKey {
|
||||
return pk.SerializeCompressed()
|
||||
}
|
||||
|
||||
@@ -7,24 +7,32 @@ package util_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/kaspanet/go-secp256k1"
|
||||
"github.com/kaspanet/kaspad/dagconfig"
|
||||
"github.com/kaspanet/kaspad/ecc"
|
||||
. "github.com/kaspanet/kaspad/util"
|
||||
)
|
||||
|
||||
func TestEncodeDecodeWIF(t *testing.T) {
|
||||
priv1, _ := ecc.PrivKeyFromBytes(ecc.S256(), []byte{
|
||||
priv1, err := secp256k1.DeserializePrivateKey(&secp256k1.SerializedPrivateKey{
|
||||
0x0c, 0x28, 0xfc, 0xa3, 0x86, 0xc7, 0xa2, 0x27,
|
||||
0x60, 0x0b, 0x2f, 0xe5, 0x0b, 0x7c, 0xae, 0x11,
|
||||
0xec, 0x86, 0xd3, 0xbf, 0x1f, 0xbe, 0x47, 0x1b,
|
||||
0xe8, 0x98, 0x27, 0xe1, 0x9d, 0x72, 0xaa, 0x1d})
|
||||
|
||||
priv2, _ := ecc.PrivKeyFromBytes(ecc.S256(), []byte{
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
priv2, err := secp256k1.DeserializePrivateKey(&secp256k1.SerializedPrivateKey{
|
||||
0xdd, 0xa3, 0x5a, 0x14, 0x88, 0xfb, 0x97, 0xb6,
|
||||
0xeb, 0x3f, 0xe6, 0xe9, 0xef, 0x2a, 0x25, 0x81,
|
||||
0x4e, 0x39, 0x6f, 0xb5, 0xdc, 0x29, 0x5f, 0xe9,
|
||||
0x94, 0xb9, 0x67, 0x89, 0xb2, 0x1a, 0x03, 0x98})
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
wif1, err := NewWIF(priv1, dagconfig.MainnetParams.PrivateKeyID, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
Reference in New Issue
Block a user