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