Merge pull request #4542 from Crypt-iQ/mock_signer_cleanup_0817
multi: remove mock.go
This commit is contained in:
27 files changed
+739
-991
No files matched your search
@@ -0,0 +1,34 @@
|
||||
package mock
|
||||
|
||||
import (
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
)
|
||||
|
||||
// ChainIO is a mock implementation of the BlockChainIO interface.
|
||||
type ChainIO struct {
|
||||
BestHeight int32
|
||||
}
|
||||
|
||||
// GetBestBlock currently returns dummy values.
|
||||
func (c *ChainIO) GetBestBlock() (*chainhash.Hash, int32, error) {
|
||||
return chaincfg.TestNet3Params.GenesisHash, c.BestHeight, nil
|
||||
}
|
||||
|
||||
// GetUtxo currently returns dummy values.
|
||||
func (c *ChainIO) GetUtxo(op *wire.OutPoint, _ []byte,
|
||||
heightHint uint32, _ <-chan struct{}) (*wire.TxOut, error) {
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// GetBlockHash currently returns dummy values.
|
||||
func (c *ChainIO) GetBlockHash(blockHeight int64) (*chainhash.Hash, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// GetBlock currently returns dummy values.
|
||||
func (c *ChainIO) GetBlock(blockHash *chainhash.Hash) (*wire.MsgBlock, error) {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package mock
|
||||
|
||||
import (
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
)
|
||||
|
||||
// ChainNotifier is a mock implementation of the ChainNotifier interface.
|
||||
type ChainNotifier struct {
|
||||
SpendChan chan *chainntnfs.SpendDetail
|
||||
EpochChan chan *chainntnfs.BlockEpoch
|
||||
ConfChan chan *chainntnfs.TxConfirmation
|
||||
}
|
||||
|
||||
// RegisterConfirmationsNtfn returns a ConfirmationEvent that contains a channel
|
||||
// that the tx confirmation will go over.
|
||||
func (c *ChainNotifier) RegisterConfirmationsNtfn(txid *chainhash.Hash,
|
||||
pkScript []byte, numConfs, heightHint uint32) (*chainntnfs.ConfirmationEvent,
|
||||
error) {
|
||||
|
||||
return &chainntnfs.ConfirmationEvent{
|
||||
Confirmed: c.ConfChan,
|
||||
Cancel: func() {},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// RegisterSpendNtfn returns a SpendEvent that contains a channel that the spend
|
||||
// details will go over.
|
||||
func (c *ChainNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint,
|
||||
pkScript []byte, heightHint uint32) (*chainntnfs.SpendEvent, error) {
|
||||
|
||||
return &chainntnfs.SpendEvent{
|
||||
Spend: c.SpendChan,
|
||||
Cancel: func() {},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// RegisterBlockEpochNtfn returns a BlockEpochEvent that contains a channel that
|
||||
// block epochs will go over.
|
||||
func (c *ChainNotifier) RegisterBlockEpochNtfn(blockEpoch *chainntnfs.BlockEpoch) (
|
||||
*chainntnfs.BlockEpochEvent, error) {
|
||||
|
||||
return &chainntnfs.BlockEpochEvent{
|
||||
Epochs: c.EpochChan,
|
||||
Cancel: func() {},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Start currently returns a dummy value.
|
||||
func (c *ChainNotifier) Start() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Started currently returns a dummy value.
|
||||
func (c *ChainNotifier) Started() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Stop currently returns a dummy value.
|
||||
func (c *ChainNotifier) Stop() error {
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package mock
|
||||
|
||||
import (
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
)
|
||||
|
||||
// SecretKeyRing is a mock implementation of the SecretKeyRing interface.
|
||||
type SecretKeyRing struct {
|
||||
RootKey *btcec.PrivateKey
|
||||
}
|
||||
|
||||
// DeriveNextKey currently returns dummy values.
|
||||
func (s *SecretKeyRing) DeriveNextKey(keyFam keychain.KeyFamily) (
|
||||
keychain.KeyDescriptor, error) {
|
||||
|
||||
return keychain.KeyDescriptor{
|
||||
PubKey: s.RootKey.PubKey(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DeriveKey currently returns dummy values.
|
||||
func (s *SecretKeyRing) DeriveKey(keyLoc keychain.KeyLocator) (keychain.KeyDescriptor,
|
||||
error) {
|
||||
return keychain.KeyDescriptor{
|
||||
PubKey: s.RootKey.PubKey(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DerivePrivKey currently returns dummy values.
|
||||
func (s *SecretKeyRing) DerivePrivKey(keyDesc keychain.KeyDescriptor) (*btcec.PrivateKey,
|
||||
error) {
|
||||
return s.RootKey, nil
|
||||
}
|
||||
|
||||
// ECDH currently returns dummy values.
|
||||
func (s *SecretKeyRing) ECDH(_ keychain.KeyDescriptor, pubKey *btcec.PublicKey) ([32]byte,
|
||||
error) {
|
||||
|
||||
return [32]byte{}, nil
|
||||
}
|
||||
|
||||
// SignDigest signs the passed digest and ignores the KeyDescriptor.
|
||||
func (s *SecretKeyRing) SignDigest(_ keychain.KeyDescriptor,
|
||||
digest [32]byte) (*btcec.Signature, error) {
|
||||
|
||||
return s.RootKey.Sign(digest[:])
|
||||
}
|
||||
|
||||
// SignDigestCompact signs the passed digest.
|
||||
func (s *SecretKeyRing) SignDigestCompact(_ keychain.KeyDescriptor,
|
||||
digest [32]byte) ([]byte, error) {
|
||||
|
||||
return btcec.SignCompact(btcec.S256(), s.RootKey, digest[:], true)
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package mock
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
)
|
||||
|
||||
// DummySignature is a dummy Signature implementation.
|
||||
type DummySignature struct{}
|
||||
|
||||
// Serialize returns an empty byte slice.
|
||||
func (d *DummySignature) Serialize() []byte {
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
// Verify always returns true.
|
||||
func (d *DummySignature) Verify(_ []byte, _ *btcec.PublicKey) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// DummySigner is an implementation of the Signer interface that returns
|
||||
// dummy values when called.
|
||||
type DummySigner struct{}
|
||||
|
||||
// SignOutputRaw returns a dummy signature.
|
||||
func (d *DummySigner) SignOutputRaw(tx *wire.MsgTx,
|
||||
signDesc *input.SignDescriptor) (input.Signature, error) {
|
||||
|
||||
return &DummySignature{}, nil
|
||||
}
|
||||
|
||||
// ComputeInputScript returns nil for both values.
|
||||
func (d *DummySigner) ComputeInputScript(tx *wire.MsgTx,
|
||||
signDesc *input.SignDescriptor) (*input.Script, error) {
|
||||
|
||||
return &input.Script{}, nil
|
||||
}
|
||||
|
||||
// SingleSigner is an implementation of the Signer interface that signs
|
||||
// everything with a single private key.
|
||||
type SingleSigner struct {
|
||||
Privkey *btcec.PrivateKey
|
||||
}
|
||||
|
||||
// SignOutputRaw generates a signature for the passed transaction using the
|
||||
// stored private key.
|
||||
func (s *SingleSigner) SignOutputRaw(tx *wire.MsgTx,
|
||||
signDesc *input.SignDescriptor) (input.Signature, error) {
|
||||
|
||||
amt := signDesc.Output.Value
|
||||
witnessScript := signDesc.WitnessScript
|
||||
privKey := s.Privkey
|
||||
|
||||
if !privKey.PubKey().IsEqual(signDesc.KeyDesc.PubKey) {
|
||||
return nil, fmt.Errorf("incorrect key passed")
|
||||
}
|
||||
|
||||
switch {
|
||||
case signDesc.SingleTweak != nil:
|
||||
privKey = input.TweakPrivKey(privKey,
|
||||
signDesc.SingleTweak)
|
||||
case signDesc.DoubleTweak != nil:
|
||||
privKey = input.DeriveRevocationPrivKey(privKey,
|
||||
signDesc.DoubleTweak)
|
||||
}
|
||||
|
||||
sig, err := txscript.RawTxInWitnessSignature(tx, signDesc.SigHashes,
|
||||
signDesc.InputIndex, amt, witnessScript, signDesc.HashType,
|
||||
privKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return btcec.ParseDERSignature(sig[:len(sig)-1], btcec.S256())
|
||||
}
|
||||
|
||||
// ComputeInputScript computes an input script with the stored private key
|
||||
// given a transaction and a SignDescriptor.
|
||||
func (s *SingleSigner) ComputeInputScript(tx *wire.MsgTx,
|
||||
signDesc *input.SignDescriptor) (*input.Script, error) {
|
||||
|
||||
privKey := s.Privkey
|
||||
|
||||
switch {
|
||||
case signDesc.SingleTweak != nil:
|
||||
privKey = input.TweakPrivKey(privKey,
|
||||
signDesc.SingleTweak)
|
||||
case signDesc.DoubleTweak != nil:
|
||||
privKey = input.DeriveRevocationPrivKey(privKey,
|
||||
signDesc.DoubleTweak)
|
||||
}
|
||||
|
||||
witnessScript, err := txscript.WitnessSignature(tx, signDesc.SigHashes,
|
||||
signDesc.InputIndex, signDesc.Output.Value, signDesc.Output.PkScript,
|
||||
signDesc.HashType, privKey, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &input.Script{
|
||||
Witness: witnessScript,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SignMessage takes a public key and a message and only signs the message
|
||||
// with the stored private key if the public key matches the private key.
|
||||
func (s *SingleSigner) SignMessage(pubKey *btcec.PublicKey,
|
||||
msg []byte) (input.Signature, error) {
|
||||
|
||||
if !pubKey.IsEqual(s.Privkey.PubKey()) {
|
||||
return nil, fmt.Errorf("unknown public key")
|
||||
}
|
||||
|
||||
digest := chainhash.DoubleHashB(msg)
|
||||
sign, err := s.Privkey.Sign(digest)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't sign the message: %v", err)
|
||||
}
|
||||
|
||||
return sign, nil
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package mock
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
)
|
||||
|
||||
// SpendNotifier extends the mock.ChainNotifier so that spend
|
||||
// notifications can be triggered and delivered to subscribers.
|
||||
type SpendNotifier struct {
|
||||
*ChainNotifier
|
||||
spendMap map[wire.OutPoint][]chan *chainntnfs.SpendDetail
|
||||
spends map[wire.OutPoint]*chainntnfs.SpendDetail
|
||||
mtx sync.Mutex
|
||||
}
|
||||
|
||||
// MakeMockSpendNotifier creates a SpendNotifier.
|
||||
func MakeMockSpendNotifier() *SpendNotifier {
|
||||
return &SpendNotifier{
|
||||
ChainNotifier: &ChainNotifier{
|
||||
SpendChan: make(chan *chainntnfs.SpendDetail),
|
||||
EpochChan: make(chan *chainntnfs.BlockEpoch),
|
||||
ConfChan: make(chan *chainntnfs.TxConfirmation),
|
||||
},
|
||||
spendMap: make(map[wire.OutPoint][]chan *chainntnfs.SpendDetail),
|
||||
spends: make(map[wire.OutPoint]*chainntnfs.SpendDetail),
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterSpendNtfn registers a spend notification for a specified outpoint.
|
||||
func (s *SpendNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint,
|
||||
_ []byte, heightHint uint32) (*chainntnfs.SpendEvent, error) {
|
||||
|
||||
s.mtx.Lock()
|
||||
defer s.mtx.Unlock()
|
||||
|
||||
spendChan := make(chan *chainntnfs.SpendDetail, 1)
|
||||
if detail, ok := s.spends[*outpoint]; ok {
|
||||
// Deliver spend immediately if details are already known.
|
||||
spendChan <- &chainntnfs.SpendDetail{
|
||||
SpentOutPoint: detail.SpentOutPoint,
|
||||
SpendingHeight: detail.SpendingHeight,
|
||||
SpendingTx: detail.SpendingTx,
|
||||
SpenderTxHash: detail.SpenderTxHash,
|
||||
SpenderInputIndex: detail.SpenderInputIndex,
|
||||
}
|
||||
} else {
|
||||
// Otherwise, queue the notification for delivery if the spend
|
||||
// is ever received.
|
||||
s.spendMap[*outpoint] = append(s.spendMap[*outpoint], spendChan)
|
||||
}
|
||||
|
||||
return &chainntnfs.SpendEvent{
|
||||
Spend: spendChan,
|
||||
Cancel: func() {},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Spend dispatches SpendDetails to all subscribers of the outpoint. The details
|
||||
// will includethe transaction and height provided by the caller.
|
||||
func (s *SpendNotifier) Spend(outpoint *wire.OutPoint, height int32,
|
||||
txn *wire.MsgTx) {
|
||||
|
||||
s.mtx.Lock()
|
||||
defer s.mtx.Unlock()
|
||||
|
||||
txnHash := txn.TxHash()
|
||||
details := &chainntnfs.SpendDetail{
|
||||
SpentOutPoint: outpoint,
|
||||
SpendingHeight: height,
|
||||
SpendingTx: txn,
|
||||
SpenderTxHash: &txnHash,
|
||||
SpenderInputIndex: outpoint.Index,
|
||||
}
|
||||
|
||||
// Cache details in case of late registration.
|
||||
if _, ok := s.spends[*outpoint]; !ok {
|
||||
s.spends[*outpoint] = details
|
||||
}
|
||||
|
||||
// Deliver any backlogged spend notifications.
|
||||
if spendChans, ok := s.spendMap[*outpoint]; ok {
|
||||
delete(s.spendMap, *outpoint)
|
||||
for _, spendChan := range spendChans {
|
||||
spendChan <- &chainntnfs.SpendDetail{
|
||||
SpentOutPoint: details.SpentOutPoint,
|
||||
SpendingHeight: details.SpendingHeight,
|
||||
SpendingTx: details.SpendingTx,
|
||||
SpenderTxHash: details.SpenderTxHash,
|
||||
SpenderInputIndex: details.SpenderInputIndex,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
package mock
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/btcsuite/btcwallet/wallet/txauthor"
|
||||
"github.com/btcsuite/btcwallet/wtxmgr"
|
||||
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
)
|
||||
|
||||
var (
|
||||
CoinPkScript, _ = hex.DecodeString("001431df1bde03c074d0cf21ea2529427e1499b8f1de")
|
||||
)
|
||||
|
||||
// WalletController is a mock implementation of the WalletController
|
||||
// interface. It let's us mock the interaction with the bitcoin network.
|
||||
type WalletController struct {
|
||||
RootKey *btcec.PrivateKey
|
||||
PublishedTransactions chan *wire.MsgTx
|
||||
index uint32
|
||||
Utxos []*lnwallet.Utxo
|
||||
}
|
||||
|
||||
// BackEnd returns "mock" to signify a mock wallet controller.
|
||||
func (w *WalletController) BackEnd() string {
|
||||
return "mock"
|
||||
}
|
||||
|
||||
// FetchInputInfo will be called to get info about the inputs to the funding
|
||||
// transaction.
|
||||
func (w *WalletController) FetchInputInfo(
|
||||
prevOut *wire.OutPoint) (*lnwallet.Utxo, error) {
|
||||
|
||||
utxo := &lnwallet.Utxo{
|
||||
AddressType: lnwallet.WitnessPubKey,
|
||||
Value: 10 * btcutil.SatoshiPerBitcoin,
|
||||
PkScript: []byte("dummy"),
|
||||
Confirmations: 1,
|
||||
OutPoint: *prevOut,
|
||||
}
|
||||
return utxo, nil
|
||||
}
|
||||
|
||||
// ConfirmedBalance currently returns dummy values.
|
||||
func (w *WalletController) ConfirmedBalance(confs int32) (btcutil.Amount, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// NewAddress is called to get new addresses for delivery, change etc.
|
||||
func (w *WalletController) NewAddress(addrType lnwallet.AddressType,
|
||||
change bool) (btcutil.Address, error) {
|
||||
|
||||
addr, _ := btcutil.NewAddressPubKey(
|
||||
w.RootKey.PubKey().SerializeCompressed(), &chaincfg.MainNetParams,
|
||||
)
|
||||
return addr, nil
|
||||
}
|
||||
|
||||
// LastUnusedAddress currently returns dummy values.
|
||||
func (w *WalletController) LastUnusedAddress(addrType lnwallet.AddressType) (
|
||||
btcutil.Address, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// IsOurAddress currently returns a dummy value.
|
||||
func (w *WalletController) IsOurAddress(a btcutil.Address) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// SendOutputs currently returns dummy values.
|
||||
func (w *WalletController) SendOutputs(outputs []*wire.TxOut,
|
||||
_ chainfee.SatPerKWeight, _ string) (*wire.MsgTx, error) {
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// CreateSimpleTx currently returns dummy values.
|
||||
func (w *WalletController) CreateSimpleTx(outputs []*wire.TxOut,
|
||||
_ chainfee.SatPerKWeight, _ bool) (*txauthor.AuthoredTx, error) {
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// ListUnspentWitness is called by the wallet when doing coin selection. We just
|
||||
// need one unspent for the funding transaction.
|
||||
func (w *WalletController) ListUnspentWitness(minconfirms,
|
||||
maxconfirms int32) ([]*lnwallet.Utxo, error) {
|
||||
|
||||
// If the mock already has a list of utxos, return it.
|
||||
if w.Utxos != nil {
|
||||
return w.Utxos, nil
|
||||
}
|
||||
|
||||
// Otherwise create one to return.
|
||||
utxo := &lnwallet.Utxo{
|
||||
AddressType: lnwallet.WitnessPubKey,
|
||||
Value: btcutil.Amount(10 * btcutil.SatoshiPerBitcoin),
|
||||
PkScript: CoinPkScript,
|
||||
OutPoint: wire.OutPoint{
|
||||
Hash: chainhash.Hash{},
|
||||
Index: w.index,
|
||||
},
|
||||
}
|
||||
atomic.AddUint32(&w.index, 1)
|
||||
var ret []*lnwallet.Utxo
|
||||
ret = append(ret, utxo)
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// ListTransactionDetails currently returns dummy values.
|
||||
func (w *WalletController) ListTransactionDetails(_,
|
||||
_ int32) ([]*lnwallet.TransactionDetail, error) {
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// LockOutpoint currently does nothing.
|
||||
func (w *WalletController) LockOutpoint(o wire.OutPoint) {}
|
||||
|
||||
// UnlockOutpoint currently does nothing.
|
||||
func (w *WalletController) UnlockOutpoint(o wire.OutPoint) {}
|
||||
|
||||
// LeaseOutput returns the current time and a nil error.
|
||||
func (w *WalletController) LeaseOutput(wtxmgr.LockID, wire.OutPoint) (time.Time,
|
||||
error) {
|
||||
|
||||
return time.Now(), nil
|
||||
}
|
||||
|
||||
// ReleaseOutput currently does nothing.
|
||||
func (w *WalletController) ReleaseOutput(wtxmgr.LockID, wire.OutPoint) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// PublishTransaction sends a transaction to the PublishedTransactions chan.
|
||||
func (w *WalletController) PublishTransaction(tx *wire.MsgTx, _ string) error {
|
||||
w.PublishedTransactions <- tx
|
||||
return nil
|
||||
}
|
||||
|
||||
// LabelTransaction currently does nothing.
|
||||
func (w *WalletController) LabelTransaction(_ chainhash.Hash, _ string,
|
||||
_ bool) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SubscribeTransactions currently does nothing.
|
||||
func (w *WalletController) SubscribeTransactions() (lnwallet.TransactionSubscription,
|
||||
error) {
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// IsSynced currently returns dummy values.
|
||||
func (w *WalletController) IsSynced() (bool, int64, error) {
|
||||
return true, int64(0), nil
|
||||
}
|
||||
|
||||
// GetRecoveryInfo currently returns dummy values.
|
||||
func (w *WalletController) GetRecoveryInfo() (bool, float64, error) {
|
||||
return true, float64(1), nil
|
||||
}
|
||||
|
||||
// Start currently does nothing.
|
||||
func (w *WalletController) Start() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stop currently does nothing.
|
||||
func (w *WalletController) Stop() error {
|
||||
return nil
|
||||
}
|
||||
Reference in new issue
Block a user