Skip to content

Commit

Permalink
Use virtual tx size for fee calculations.
Browse files Browse the repository at this point in the history
  • Loading branch information
tecnovert committed Oct 24, 2017
1 parent b9cc0e6 commit 545f4ac
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 41 deletions.
2 changes: 1 addition & 1 deletion Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 14 additions & 13 deletions cmd/partatomicswap/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -684,18 +684,17 @@ func buildRefund(c *rpc.Client, contract []byte, contractTx *wire.MsgTx, feePerK

refundTx = wire.NewMsgTx(txVersion)
refundTx.LockTime = uint32(pushes.LockTime)
txIn := wire.NewTxIn(&contractOutPoint, nil, nil)
txIn.Sequence = 0
refundTx.AddTxIn(txIn)
refundTx.AddTxOut(wire.NewTxOut(0, refundOutScript)) // amount set below
refundSize := estimateRefundSerializeSize(contract, refundTx.TxOut)

refundSize := estimateRefundSerializeSize(contract, refundTx)
refundFee = txrules.FeeForSerializeSize(feePerKb, refundSize)
refundTx.TxOut[0].Value = contractTx.TxOut[contractOutPoint.Index].Value - int64(refundFee)
if txrules.IsDustOutput(refundTx.TxOut[0], minFeePerKb) {
return nil, 0, fmt.Errorf("refund output value of %v is dust", partutil.Amount(refundTx.TxOut[0].Value))
}

txIn := wire.NewTxIn(&contractOutPoint, nil, nil)
txIn.Sequence = 0
refundTx.AddTxIn(txIn)

refundSig, refundPubKey, err := createSig(refundTx, 0, inputAmount, contract, refundAddr, c)
if err != nil {
return nil, 0, err
Expand Down Expand Up @@ -759,8 +758,9 @@ func (cmd *initiateCmd) runCommand(c *rpc.Client) error {
}

refundTxHash := b.refundTx.TxHash()
contractFeePerKb := calcFeePerKb(b.contractFee, b.contractTx.SerializeSize())
refundFeePerKb := calcFeePerKb(b.refundFee, b.refundTx.SerializeSize())

contractFeePerKb := calcFeePerKb(b.contractFee, getVirtualSize(b.contractTx))
refundFeePerKb := calcFeePerKb(b.refundFee, getVirtualSize(b.refundTx))

fmt.Printf("Secret: %x\n", secret)
fmt.Printf("Secret hash: %x\n\n", secretHash)
Expand Down Expand Up @@ -798,8 +798,9 @@ func (cmd *participateCmd) runCommand(c *rpc.Client) error {
}

refundTxHash := b.refundTx.TxHash()
contractFeePerKb := calcFeePerKb(b.contractFee, b.contractTx.SerializeSize())
refundFeePerKb := calcFeePerKb(b.refundFee, b.refundTx.SerializeSize())

contractFeePerKb := calcFeePerKb(b.contractFee, getVirtualSize(b.contractTx))
refundFeePerKb := calcFeePerKb(b.refundFee, getVirtualSize(b.refundTx))

fmt.Printf("Contract fee: %v (%0.8f PART/kB)\n", b.contractFee, contractFeePerKb)
fmt.Printf("Refund fee: %v (%0.8f PART/kB)\n\n", b.refundFee, refundFeePerKb)
Expand Down Expand Up @@ -870,7 +871,7 @@ func (cmd *redeemCmd) runCommand(c *rpc.Client) error {
redeemTx.LockTime = uint32(pushes.LockTime)
redeemTx.AddTxIn(wire.NewTxIn(&contractOutPoint, nil, nil))
redeemTx.AddTxOut(wire.NewTxOut(0, outScript)) // amount set below
redeemSize := estimateRedeemSerializeSize(cmd.contract, redeemTx.TxOut)
redeemSize := estimateRedeemSerializeSize(cmd.contract, redeemTx)
fee := txrules.FeeForSerializeSize(feePerKb, redeemSize)
redeemTx.TxOut[0].Value = cmd.contractTx.TxOut[contractOut].Value - int64(fee)
if txrules.IsDustOutput(redeemTx.TxOut[0], minFeePerKb) {
Expand All @@ -892,7 +893,7 @@ func (cmd *redeemCmd) runCommand(c *rpc.Client) error {
redeemTx.TxIn[0].Witness = wire.TxWitness{redeemSig, redeemPubKey, cmd.secret, b1, cmd.contract}

redeemTxHash := redeemTx.TxHash()
redeemFeePerKb := calcFeePerKb(fee, redeemTx.SerializeSize())
redeemFeePerKb := calcFeePerKb(fee, getVirtualSize(redeemTx))

var buf bytes.Buffer
buf.Grow(redeemTx.SerializeSize())
Expand Down Expand Up @@ -940,7 +941,7 @@ func (cmd *refundCmd) runCommand(c *rpc.Client) error {
buf.Grow(refundTx.SerializeSize())
refundTx.Serialize(&buf)

refundFeePerKb := calcFeePerKb(refundFee, refundTx.SerializeSize())
refundFeePerKb := calcFeePerKb(refundFee, getVirtualSize(refundTx))

fmt.Printf("Refund fee: %v (%0.8f PART/kB)\n\n", refundFee, refundFeePerKb)
fmt.Printf("Refund transaction (%v):\n", &refundTxHash)
Expand Down
47 changes: 20 additions & 27 deletions cmd/partatomicswap/sizeest.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
package main

import (
"github.com/particl/partsuite_partd/txscript"
"github.com/particl/partsuite_partd/wire"
)

Expand Down Expand Up @@ -39,13 +38,23 @@ const (
refundAtomicSwapSigScriptSize = 1 + 73 + 1 + 33 + 1
)

const WITNESS_SCALE_FACTOR = 2

func sumOutputSerializeSizes(outputs []*wire.TxOut) (serializeSize int) {
for _, txOut := range outputs {
serializeSize += txOut.SerializeSize()
}
return serializeSize
}

func getVirtualSizeInner(sizeNoWitness int, sizeTotal int) int {
return ((sizeNoWitness * (WITNESS_SCALE_FACTOR-1) + sizeTotal) + WITNESS_SCALE_FACTOR-1) / WITNESS_SCALE_FACTOR
}

func getVirtualSize(tx *wire.MsgTx) int {
return getVirtualSizeInner(tx.SerializeSizeStripped(), tx.SerializeSize())
}

// inputSize returns the size of the transaction input needed to include a
// signature script with size sigScriptSize. It is calculated as:
//
Expand All @@ -60,34 +69,18 @@ func inputSize(sigScriptSize int) int {

// estimateRedeemSerializeSize returns a worst case serialize size estimates for
// a transaction that redeems an atomic swap P2SH output.
func estimateRedeemSerializeSize(contract []byte, txOuts []*wire.TxOut) int {
contractPush, err := txscript.NewScriptBuilder().AddData(contract).Script()
if err != nil {
// Should never be hit since this script does exceed the limits.
panic(err)
}
contractPushSize := len(contractPush)

// 12 additional bytes are for version, locktime and expiry.
return 12 + wire.VarIntSerializeSize(1) +
wire.VarIntSerializeSize(uint64(len(txOuts))) +
inputSize(redeemAtomicSwapSigScriptSize+contractPushSize) +
sumOutputSerializeSizes(txOuts)
func estimateRedeemSerializeSize(contract []byte, tx *wire.MsgTx) int {
baseSize := tx.SerializeSize()
// varintsize(height of stack) + height of stack, redeemSig, redeemPubKey, secret, b1, contract
witnessSize := 6 + 73 + 33 + 32 + 1 + len(contract)
return getVirtualSizeInner(baseSize, baseSize + witnessSize)
}

// estimateRefundSerializeSize returns a worst case serialize size estimates for
// a transaction that refunds an atomic swap P2SH output.
func estimateRefundSerializeSize(contract []byte, txOuts []*wire.TxOut) int {
contractPush, err := txscript.NewScriptBuilder().AddData(contract).Script()
if err != nil {
// Should never be hit since this script does exceed the limits.
panic(err)
}
contractPushSize := len(contractPush)

// 12 additional bytes are for version, locktime and expiry.
return 12 + wire.VarIntSerializeSize(1) +
wire.VarIntSerializeSize(uint64(len(txOuts))) +
inputSize(refundAtomicSwapSigScriptSize+contractPushSize) +
sumOutputSerializeSizes(txOuts)
func estimateRefundSerializeSize(contract []byte, tx *wire.MsgTx) int {
baseSize := tx.SerializeSize()
// varintsize(height of stack) + height of stack, refundSig, refundPubKey, b0, contract
witnessSize := 5 + 73 + 33 + 1 + len(contract)
return getVirtualSizeInner(baseSize, baseSize + witnessSize)
}

0 comments on commit 545f4ac

Please sign in to comment.