-
Notifications
You must be signed in to change notification settings - Fork 81
/
txsize.go
79 lines (73 loc) · 2.85 KB
/
txsize.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
// Copyright 2018 Shift Devices AG
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package maketx
import (
"github.com/btcsuite/btcd/wire"
"github.com/digitalbitbox/bitbox-wallet-app/backend/coins/btc/addresses"
"github.com/digitalbitbox/bitbox-wallet-app/backend/signing"
)
func calcInputSize(sigScriptSize int) int {
// inputSize: 32 prevHash + 4 prevIndex + sigScript + 4 sequence
return 32 + 4 + wire.VarIntSerializeSize(uint64(sigScriptSize)) + sigScriptSize + 4
}
func outputSize(pkScriptSize int) int {
if pkScriptSize == 0 {
return 0
}
return 8 + wire.VarIntSerializeSize(uint64(pkScriptSize)) + pkScriptSize
}
// estimateTxSize gives the worst case tx size estimate. All inputs are assumed to be of the same
// structure.
// inputCount is the number of inputs in the tx.
// inputConfiguration defines the structure of every input.
// outputPkScriptSize is the size of the output pkScript. One output is assumed (apart from change).
// changePkScriptSize is the size of the change pkScript. A value of 0 means that there is no change output.
// This function computes the virtual size of a transaction, taking segwit discount into account.
func estimateTxSize(
inputCount int,
inputConfiguration *signing.Configuration,
outputPkScriptSize int,
changePkScriptSize int) int {
const (
outputCount = 2 // 1 output + 1 change output
versionSize = 4
lockTimeSize = 4
nonWitness = 4 // factor for non-witness fields
)
sigScriptSize, hasWitness := addresses.SigScriptWitnessSize(inputConfiguration)
inputSize := calcInputSize(sigScriptSize)
txWeight := nonWitness * (versionSize + lockTimeSize + wire.VarIntSerializeSize(uint64(inputCount)) +
wire.VarIntSerializeSize(uint64(outputCount)) +
inputCount*inputSize +
outputSize(outputPkScriptSize) +
outputSize(changePkScriptSize))
if hasWitness {
// For now, every input has a witness serialization of this format:
// <serialized sig> <serialized compressed pubkey>
const (
signatureSize = 73 // including SIGHASH op
pubkeySize = 33
)
witnessSize := wire.VarIntSerializeSize(2) +
wire.VarIntSerializeSize(signatureSize) + signatureSize +
wire.VarIntSerializeSize(pubkeySize) + pubkeySize
txWeight += inputCount * witnessSize
txWeight += 2 // segwit marker + segwit flag
}
// return txWeight/4 rounded up.
if txWeight%4 == 0 {
return txWeight / 4
}
return txWeight/4 + 1
}