forked from ethereum/btcrelay
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbtcSpecialTx.se
115 lines (79 loc) · 3.18 KB
/
btcSpecialTx.se
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# This file retrieves the first 2 outputs of a Bitcoin transaction's raw bytes
# read the VarInt and advance the cursor
macro m_parseVarInt($txBytes, $cursor):
$arr = m_getVarintNum($txBytes, $cursor)
$cursor += $arr[0]
$arr[1]
# event log_dbg(dbgData)
# return 0 if tx has less than 2 outputs
# or other error, otherwise return array
# of [out1stSatoshis, out1stScriptIndex, out2ndScriptIndex]
def getFirst2Outputs(txBytes:str):
cursor = 4 # skip version
numIns = m_parseVarInt(txBytes, cursor)
# log(type=log_dbg, numIns)
# log(type=log_dbg, cursor)
i = 0
while i < numIns:
cursor += 36 # skip prevTxId (32) and outputIndex (4)
scriptSize = m_parseVarInt(txBytes, cursor)
cursor += scriptSize + 4 # skip input script and seqNum (4)
i += 1
numOuts = m_parseVarInt(txBytes, cursor)
if numOuts < 2:
return
###########################################################
# 1st output
tmpArr = m_getUInt64LE(txBytes, cursor) # new m_getUInt64LE
cursor += 8
out1stSatoshis = tmpArr[1]
# log(satoshis)
scriptSize = m_parseVarInt(txBytes, cursor)
# log(scriptSize)
if scriptSize == 0:
return
out1stScriptIndex = cursor
cursor += scriptSize + 8 # skip script and 2nd output's satoshis (8)
###########################################################
###########################################################
# 2nd output (satoshis were already skipped in previous line)
scriptSize = m_parseVarInt(txBytes, cursor)
# log(scriptSize)
if scriptSize == 0:
return
out2ndScriptIndex = cursor
###########################################################
return([out1stSatoshis, out1stScriptIndex, out2ndScriptIndex]:arr)
macro m_getVarintNum($txBytes, $pos):
$ret = m_getUInt8($txBytes, $pos)
if $ret == 0xfd:
$ret = m_getUInt16LE($txBytes, $pos)
elif $ret == 0xfe:
$ret = m_getUInt32LE($txBytes, $pos)
elif $ret == 0xff:
$ret = m_getUInt64LE($txBytes, $pos)
$ret
macro m_getUInt8($txBytes, $pos):
self.getBytesLE($txBytes, $pos, 8, outitems=2)
macro m_getUInt16LE($txBytes, $pos):
self.getBytesLE($txBytes, $pos, 16, outitems=2)
macro m_getUInt32LE($txBytes, $pos):
self.getBytesLE($txBytes, $pos, 32, outitems=2)
macro m_getUInt64LE($txBytes, $pos):
self.getBytesLE($txBytes, $pos, 64, outitems=2)
macro BYTES_1: 2**8
macro BYTES_2: 2**16
macro BYTES_3: 2**24
macro BYTES_4: 2**32
macro BYTES_5: 2**40
macro BYTES_6: 2**48
macro BYTES_7: 2**56
def getBytesLE(txBytes:str, pos, bits):
if bits == 8:
return([1, getch(txBytes, pos)]:arr)
if bits == 16:
return([2, getch(txBytes, pos) + getch(txBytes, pos+1)*BYTES_1]:arr)
if bits == 32:
return([4, getch(txBytes, pos) + getch(txBytes, pos+1)*BYTES_1 + getch(txBytes, pos+2)*BYTES_2 + getch(txBytes, pos+3)*BYTES_3]:arr)
if bits == 64:
return([8, getch(txBytes, pos) + getch(txBytes, pos+1)*BYTES_1 + getch(txBytes, pos+2)*BYTES_2 + getch(txBytes, pos+3)*BYTES_3 + getch(txBytes, pos+4)*BYTES_4 + getch(txBytes, pos+5)*BYTES_5 + getch(txBytes, pos+6)*BYTES_6 + getch(txBytes, pos+7)*BYTES_7]:arr)