-
Notifications
You must be signed in to change notification settings - Fork 158
/
Copy pathmultisig.go
101 lines (86 loc) · 2.87 KB
/
multisig.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// Copyright (c) 2016 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package wallet
import (
"context"
"decred.org/dcrwallet/v5/errors"
"decred.org/dcrwallet/v5/wallet/txrules"
"decred.org/dcrwallet/v5/wallet/txsizes"
"decred.org/dcrwallet/v5/wallet/udb"
"decred.org/dcrwallet/v5/wallet/walletdb"
"github.com/decred/dcrd/txscript/v4/stdaddr"
"github.com/decred/dcrd/wire"
)
// FetchP2SHMultiSigOutput fetches information regarding a wallet's P2SH
// multi-signature output.
func (w *Wallet) FetchP2SHMultiSigOutput(ctx context.Context, outPoint *wire.OutPoint) (*P2SHMultiSigOutput, error) {
const op errors.Op = "wallet.FetchP2SHMultiSigOutput"
var (
mso *udb.MultisigOut
redeemScript []byte
)
err := walletdb.View(ctx, w.db, func(tx walletdb.ReadTx) error {
addrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey)
txmgrNs := tx.ReadBucket(wtxmgrNamespaceKey)
var err error
mso, err = w.txStore.GetMultisigOutput(txmgrNs, outPoint)
if err != nil {
return err
}
addr, _ := stdaddr.NewAddressScriptHashV0FromHash(mso.ScriptHash[:], w.chainParams)
redeemScript, err = w.manager.RedeemScript(addrmgrNs, addr)
return err
})
if err != nil {
return nil, errors.E(op, err)
}
p2shAddr, err := stdaddr.NewAddressScriptHashV0FromHash(
mso.ScriptHash[:], w.chainParams)
if err != nil {
return nil, err
}
multiSigOutput := P2SHMultiSigOutput{
OutPoint: *mso.OutPoint,
OutputAmount: mso.Amount,
ContainingBlock: BlockIdentity{
Hash: mso.BlockHash,
Height: int32(mso.BlockHeight),
},
P2SHAddress: p2shAddr,
RedeemScript: redeemScript,
M: mso.M,
N: mso.N,
Redeemer: nil,
}
if mso.Spent {
multiSigOutput.Redeemer = &OutputRedeemer{
TxHash: mso.SpentBy,
InputIndex: mso.SpentByIndex,
}
}
return &multiSigOutput, nil
}
// PrepareRedeemMultiSigOutTxOutput estimates the tx value for a MultiSigOutTx
// output and adds it to msgTx.
func (w *Wallet) PrepareRedeemMultiSigOutTxOutput(msgTx *wire.MsgTx, p2shOutput *P2SHMultiSigOutput, pkScript *[]byte) error {
const op errors.Op = "wallet.PrepareRedeemMultiSigOutTxOutput"
scriptSizes := make([]int, 0, len(msgTx.TxIn))
// generate the script sizes for the inputs
for range msgTx.TxIn {
scriptSizes = append(scriptSizes, txsizes.RedeemP2SHSigScriptSize)
}
// estimate the output fee
txOut := wire.NewTxOut(0, *pkScript)
feeSize := txsizes.EstimateSerializeSize(scriptSizes, []*wire.TxOut{txOut}, 0)
feeEst := txrules.FeeForSerializeSize(w.RelayFee(), feeSize)
if feeEst >= p2shOutput.OutputAmount {
return errors.E(op, errors.Errorf("estimated fee %v is above output value %v",
feeEst, p2shOutput.OutputAmount))
}
toReceive := p2shOutput.OutputAmount - feeEst
// set the output value and add to the tx
txOut.Value = int64(toReceive)
msgTx.AddTxOut(txOut)
return nil
}