Just as an example for the math: a two input/two output P2PKH transaction returns 746 chars, so it is in hex 373 Bytes.
$ printf 010000000253603B3FDB9D5E10DE2172305FF68F4B5227310BA6BD81D4E1BF60C0DE6183BC010000006A4730440220128487F04A591C43D7A6556FFF9158999B46D6119C1A4D4CF1F5D0AC1DD57A94022061556761E9E1B1E656C0A70AA7B3E83454CD61662DF61EBDC31E43196B5E0C10012102B12126A716CE7BBB84703BCFBF0AFA80283C75A7304A48CD311A5027EFD906C2FFFFFFFF0E52C4701577287B6DD02F422C2A8033FA0B4614F75FA9F0A5C4AB69634B5BA7000000006B483045022100A428348FF55B2B59BC55DDACB1A00F4ECDABE282707BA5185D39FE9CDF05D7F0022074232DAE76965B6311CEA2D9E5708A0F137F4EA2B0E36D0818450C67C9BA259D0121025F95E8A33556E9D7311FA748E9434B333A4ECFB590C773480A196DEAB0DEDEE1FFFFFFFF0290257300000000001976A914FCA68658B537382E27A85522D292E1AD9543FE0488AC98381100000000001976A9146AF1D17462C6146A8A61217E8648903ACD3335F188AC00000000 | wc -c
It has two inputs with signatures and compressed keys, and two P2PKH outputs. It can be decomposed this way:
VERSION 01000000
TX_IN COUNT [var_int]: hex=02, decimal=2
TX_IN[0] OutPoint hash (char[32]) BC8361DEC060BFE1D481BDA60B3127524B8FF65F307221DE105E9DDB3F3B6053
TX_IN[0] OutPoint index (uint32_t) hex=01000000, reversed=00000001, decimal=1
TX_IN[0] Script Length (var_int) hex=6A, decimal=106
TX_IN[0] Script Sig (uchar[]) 4730440220128487F04A591C43D7A6556FFF9158999B46D6119C1A4D4CF1F5D0AC1DD57A94022061556761E9E1B1E656C0A70AA7B3E83454CD61662DF61EBDC31E43196B5E0C10012102B12126A716CE7BBB84703BCFBF0AFA80283C75A7304A48CD311A5027EFD906C2
TX_IN[0] Sequence (uint32_t) FFFFFFFF
TX_IN[1]
TX_IN[1] OutPoint hash (char[32]) A75B4B6369ABC4A5F0A95FF714460BFA33802A2C422FD06D7B28771570C4520E
TX_IN[1] OutPoint index (uint32_t) hex=00000000, reversed=00000000, decimal=0
TX_IN[1] Script Length (var_int) hex=6B, decimal=107
TX_IN[1] Script Sig (uchar[]) 483045022100A428348FF55B2B59BC55DDACB1A00F4ECDABE282707BA5185D39FE9CDF05D7F0022074232DAE76965B6311CEA2D9E5708A0F137F4EA2B0E36D0818450C67C9BA259D0121025F95E8A33556E9D7311FA748E9434B333A4ECFB590C773480A196DEAB0DEDEE1
TX_IN[1] Sequence (uint32_t) FFFFFFFF
TX_OUT COUNT hex=02, decimal=2
TX_OUT[0] Value (uint64_t) hex=9025730000000000, reversed_hex=0000000000732590, dec=7546256, bitcoin=0.07546256
TX_OUT[0] PK_Script Length (var_int) hex=19, dec=25
TX_OUT[0] pk_script (uchar[]) 76A914FCA68658B537382E27A85522D292E1AD9543FE0488AC
TX_OUT[1] Value (uint64_t) hex=9838110000000000, reversed_hex=0000000000113898, dec=1128600, bitcoin=0.01128600
TX_OUT[1] PK_Script Length (var_int) hex=19, dec=25
TX_OUT[1] pk_script (uchar[]) 76A9146AF1D17462C6146A8A61217E8648903ACD3335F188AC
LOCK_TIME 00000000
Based on the formula (X * 148 + Y * 34 + 10 +- X) it should give 2*148+2*34+2=366Bytes ... close. Ok.
Now comes a (2-of-2) multisig with 1 input, two outputs, 670 chars, 335 Bytes - compressed keys:
$ printf 0100000001B9C6777F2D8D710F1E0E3BB5FBFFA7CDFD6C814A2257A7CFCED9A2205448DD0601000000DA0048304502210083A93C7611F5AEEE6B0B4D1CBFF2D31556AF4CD1F951DE8341C768AE03F780730220063B5E6DFB461291B1FBD93D58A8111D04FD03C7098834BAC5CDF1D3C5FA90D0014730440220137C7320E03B73DA66E9CF89E5F5ED0D5743EBC65E776707B8385FF93039408802202C30BC57010B3DD20507393EBC79AFFC653473A7BAF03C5ABF19C14E2136C646014752210285CB139A82DD9062B9AC1091CB1F91A01C11AB9C6A46BD09D0754DAB86A38CC9210328C37F938748DCBBF15A0E5A9D1BA20F93F2C2D0EAD63C7C14A5A10959B5CE8952AEFFFFFFFF0280C42B03000000001976A914D199925B52D367220B1E2A2D8815E635B571512F88AC65A7B3010000000017A9145C4DD14B9DF138840B34237FDBE9159C420EDBBE8700000000 | wc -c
the difference is that you need to have two signatures, and the 3 pubkeys of the multisig. Decoded:
VERSION 01000000
TX_IN COUNT [var_int]: hex=01, decimal=1
TX_IN[0] OutPoint hash (char[32]) 06DD485420A2D9CECFA757224A816CFDCDA7FFFBB53B0E1E0F718D2D7F77C6B9
TX_IN[0] OutPoint index (uint32_t) hex=01000000, reversed=00000001, decimal=1
TX_IN[0] Script Length (var_int) hex=DA, decimal=218
TX_IN[0] Script Sig 1 (uchar[]) 0048304502210083A93C7611F5AEEE6B0B4D1CBFF2D31556AF4CD1F951DE8341C768AE03F780730220063B5E6DFB461291B1FBD93D58A8111D04FD03C7098834BAC5CDF1D3C5FA90D001
TX_IN[0] Script Sig 2 (uchar[]) 4730440220137C7320E03B73DA66E9CF89E5F5ED0D5743EBC65E776707B8385FF93039408802202C30BC57010B3DD20507393EBC79AFFC653473A7BAF03C5ABF19C14E2136C64601
TX_IN[0] Multisig Pubkeys (decoded details):
47: OP_DATA_0x47: push hex 47 (decimal 71) bytes on stack
52: OP_2: the number 2 is pushed onto stack
21: OP_DATA_0x21: compressed pub key (33 Bytes)
0285CB139A82DD90:62B9AC1091CB1F91:A01C11AB9C6A46BD:09D0754DAB86A38C:C9
This is MultiSig's compressed Public Key (X9.63 form)
corresponding bitcoin address is: 1LcBDzTGSJiN5snVBHiyeWsT7SqRWUW7mp
21: OP_DATA_0x21: compressed pub key (33 Bytes)
0328C37F938748DC:BBF15A0E5A9D1BA2:0F93F2C2D0EAD63C:7C14A5A10959B5CE:89
This is MultiSig's compressed Public Key (X9.63 form)
corresponding bitcoin address is: 1LisHErVXWhY1A1ZJqZSDdGYKrbGn1M6bx
52: OP_2: the number 2 is pushed onto stack
AE: OP_CHECKMULTISIG: terminating multisig TX_IN[0] Sequence (uint32_t)
TX_IN[0] Sequence (uint32) FFFFFFFF
TX_OUT COUNT hex=02, decimal=2
TX_OUT[0] Value (uint64_t) hex=80C42B0300000000, reversed_hex=00000000032BC480, dec=53200000, bitcoin=.53200000
TX_OUT[0] PK_Script Length (var_int) hex=19, dec=25
TX_OUT[0] pk_script (uchar[]) 76A914D199925B52D367220B1E2A2D8815E635B571512F88AC
TX_OUT[1] Value (uint64_t) hex=65A7B30100000000, reversed_hex=0000000001B3A765, dec=28551013, bitcoin=.28551013
TX_OUT[1] PK_Script Length (var_int) hex=17, dec=23
TX_OUT[1] pk_script (uchar[]) A9145C4DD14B9DF138840B34237FDBE9159C420EDBBE87
LOCK_TIME 00000000
one can easily change to 2-3 multisig or 3-of-7, which would increase the number of signatures and pubkeys accordingly.
Signatures can have different length, starting with 00 (especially when having negative S-values), and then 0x47 or 0x48 as length indicator.
Pubkeys can be compressed (33 bytes) or uncompressed (66bytes).
Math can't be tricked :-)
2Could you tell us what wallet or software you're using? Is it possible that you are using a 2-of-3 multisignature wallet? 2-of-3 multisignature inputs are 295 bytes, and 295+295+34+10=634 (which is pretty close). – Murch – 2017-10-30T18:51:32.260
Electrum (up-to-date) standard wallet w/ 2FA. Again, a lot of past transactions using the same wallet add up perfectly using the compressed input sizes of 148bytes for calculation. – Philip Ingram – 2017-10-30T21:14:31.243
Or you had four inputs instead of two: 4*148+34+10 = 636. If you could link the transaction we would probably be able to tell you more. – Murch – 2017-10-30T21:23:40.180
I just found in this thread (https://bitcointalk.org/index.php?topic=2316977.msg23541254#msg23541254) explaining that when using a 2fa wallet, TrustedCoin becomes the 2nd signing party and essentially I have a multi-sig wallet without realizing this, so does that double up all inputs x 2 or simply change the input byte size to be 2 x 148 = 294?
– Philip Ingram – 2017-10-30T21:52:31.8571
related: https://bitcoin.stackexchange.com/q/30570/5406
– Murch – 2017-10-30T23:48:30.763Thx Murch but I wasn't able to gather whether my conclusion is correct about my 2FA wallet and simply multiplying all my inputs x 2 or number of signers first before multiplying by 148. i.e. (2 x (# of inputs x 148 ) + (# of outputs x 34 ) + 10 +/- # of inputs? – Philip Ingram – 2017-10-31T23:33:19.367
1No, you don't double the input size, rather the script has a different size altogether. A single 2-of-3 multisig input comes in at approximately 295 bytes. – Murch – 2017-10-31T23:37:59.680
Ah, that is exactly the clarity I needed to understand. I kind of feel like I need this in the format of answer so I choose it as the most appropriate one, as it provides more clarity that is lacking in many of the write ups found around the web on how to calc fees and transaction sizes. The first part of course was realizing 2FA adds to the size, significantly. – Philip Ingram – 2017-11-01T00:16:43.057