标签:字节截取 prepare gpu -o 源码 翻译 大量 init 判断
开篇之前先聊聊背景:本人本身是想打造一个Python版本节点的,但是坑在了两个函数dfslib_crypt_set_sector0
dfslib_encrypt_sector
这两个函数在节点和挖矿程序中都出现了,主要是对用户密码进行加密解密的函数,我尝试用Python翻译了一遍,效率极低,甚至都影响调试就放弃了。
再对Python开发者说几句,整个XDAG代码并不多,但是其中运用了大量宏,字节截取,二进制处理,内存偏移等。导致对于Python这个语言来说,增加了大量转换工作,许多源码中一行的简单调用,在Python都要经过多行函数级处理才得已实现。所以Python初中级的朋友慎入~整个挖矿流程我用Python版本跑了一遍,效率比原版差了百倍,所以Python版本仅供参考研究使用,暂时无法投放在生产环境,本人在下个版本可能会参与到Go语言版本的重构中。
言归正传,咱们走一遍整个GpuMiner都做了什么,其中涉及几个函数如下:
1, 生成_crypt变量,该变量是
MINERS_PWD经过开篇提到的两个函数加密之后得到的
2, 链接矿池,获取任务,看上去是获得了两个xdag_field结构体的任务,但其实后面是要结合起来加工的
3, 两个结构体任务分别经过dfslib_uncrypt_array函数,sectorNo参数分别是0和1
4, 通过AddressToHash函数把地址转换成Hash
5, task_ctx_data其实就是第二个获得的任务通过dfslib_uncrypt_array加密转换,再加上地址转换的Hash
6, task_ctx_state就是第一个任务通过dfslib_uncrypt_array加密之后的值
7, 变量main_time为当前时间经过GetMainTime函数的转换
8, nonce为一个2**64次方的随机数
9, minhash_data由一个数组[18446744073709551615,18446744073709551615,18446744073709551615,9895604649983]序列化得到
10, 从而可以输出所有变量如图:
11, 拿到了所有所需数据,下一步就要计算哈希了SearchMinNonce,其实这里有个小问题,SearchMinNonce得到最终是share时会多计算0-254次哈希,我个人判断,由于得到share需要经过大量哈希运算,作者为了方便编写就每256次为一组计算最小哈希,在和minhash做对比。
12, 拿到最小哈希和nonce并没有完,还需要通过dfslib_encrypt_array函数转换后,把fieldsCopy传回给矿池,整个过程结束。
本文提及的所有函数随后提供Python版本的Demo(由于时间问题,有点乱,不是很完整,多见谅),欢迎大家多多交流~
import struct
import copy
import ctypes
import time
import random
import hashlib
import numpy as np
from regs import regs
class xdag_field:
pass
class _crypt:
pass
_c = _crypt()
_c.regs = regs
_c.pwd = [781665893, 3404732475, 2212684154, 3744338274]
_readDataSize = b'\x9c\x0f_%\x19\x8c!{\x02\xed\xa7\x87h\xc6\xc4\xca\x1c\xe7Ut\xa2\xd4\x13\x993|\x9d@\xa0\xc1\xa4\n\xf6d\xa51nn\xb9\x81\xa5\xec\x8b\xdc\xc0\x1dz\xa1\xcfi5\x89\xa0K ?\xf6\x93b\xa5\x87\x8czj'
a = struct.unpack('Q',_readDataSize[0:8])[0]
b = struct.unpack('Q',_readDataSize[8:16])[0]
c = struct.unpack('Q',_readDataSize[16:24])[0]
d = struct.unpack('Q',_readDataSize[24:32])[0]
xdag_field1 = xdag_field()
xdag_field1.transport_header = a
xdag_field1.type = b
xdag_field1.time = c
xdag_field1.hash = [a, b, c]
xdag_field1.amount = d
xdag_field1.end_time = d
xdag_field1.data = [a, b, c, d]
a = struct.unpack('Q',_readDataSize[32:40])[0]
b = struct.unpack('Q',_readDataSize[40:48])[0]
c = struct.unpack('Q',_readDataSize[48:56])[0]
d = struct.unpack('Q',_readDataSize[56:64])[0]
xdag_field2 = xdag_field()
xdag_field2.transport_header = a
xdag_field2.type = b
xdag_field2.time = c
xdag_field2.hash = [a, b, c]
xdag_field2.amount = d
xdag_field2.end_time = d
xdag_field2.data = [a, b, c, d]
def dfs_crypt0(dfsc, a,x,y,z,t):
dfs64 = np.uint64(y[0])
dfs16 = np.uint16(t[0])
tmp = np.uint32(z[0] + dfsc.regs[x[0] >> 16])
dfs32 = np.uint32(int(dfs64* tmp) >> 16)
a[0] = dfs32 ^ dfsc.regs[dfs16]
return a[0]
def dfs_crypt2(dfsc, a,b,c,d,x,y,z,t):
dfs_crypt0(dfsc, a,x,y,z,t);dfs_crypt0(dfsc, b,y,z,t,x)
dfs_crypt0(dfsc, c,z,t,x,y);dfs_crypt0(dfsc, d,t,x,y,z)
def dfs_crypt3(dfsc, a,b,c,d,x,y,z,t):
dfs_crypt2(dfsc, a,b,c,d,x,y,z,t);dfs_crypt2(dfsc, x,y,z,t,a,b,c,d)
def dfs_crypt6(dfsc, a,b,c,d,x,y,z,t):
dfs_crypt3(dfsc, a,b,c,d,x,y,z,t);dfs_crypt3(dfsc, a,b,c,d,x,y,z,t)
dfs_crypt3(dfsc, a,b,c,d,x,y,z,t);dfs_crypt3(dfsc, a,b,c,d,x,y,z,t)
dfs_crypt3(dfsc, a,b,c,d,x,y,z,t);dfs_crypt3(dfsc, a,b,c,d,x,y,z,t)
dfs_crypt3(dfsc, a,b,c,d,x,y,z,t);dfs_crypt3(dfsc, a,b,c,d,x,y,z,t)
def dfs_uncrypt2(dfsc, a, b, c, d, x, y, z, t, data, num):
dfs_crypt0(dfsc, c, z, t, x, y); data[num[0]]= np.uint32(data[num[0]]) + np.uint32(dfs_crypt0(dfsc, d, t, x, y, z))
a[0] = dfs_crypt0(dfsc, a, x, y, z, t) ^ ~data[num[0]];num[0] +=1;dfs_crypt0(dfsc, b, y, z, t, x)
def dfs_uncrypt3(dfsc, a, b, c, d, x, y, z, t, data, num):
dfs_uncrypt2(dfsc, a, b, c, d, x, y, z, t, data, num);dfs_uncrypt2(dfsc, x, y, z, t, a, b, c, d, data, num)
def dfs_prepare(dfsc, sectorNo, x, y, z, t):
sectorNo = int(np.uint64(1229426917 << 32 | 3433359571) * np.uint64(sectorNo))
x[0] = dfsc.pwd[0] ^ dfsc.regs[sectorNo%65479 + 31]
y[0] = dfsc.pwd[1] ^ dfsc.regs[sectorNo%65497 + 11]
z[0] = dfsc.pwd[2] ^ dfsc.regs[sectorNo%65519 + 5]
t[0] = dfsc.pwd[3] ^ dfsc.regs[sectorNo%65521 + 3]
a, b, c, d = [0], [0], [0], [0]
dfs_crypt6(dfsc, a,b,c,d,x,y,z,t)
def dfs_unmix2(c, d, num):
c[0] = np.uint32(c[0] * 43385317);
num[0]-=1;
d[num[0]] ^=c[0]; c[0] ^= d[num[0]]
def dfs_unmixArray(d, num):
c = [1615037507]
for i in range(8):
dfs_unmix2(c, d, num)
def dfslib_uncrypt_array(dfsc, data, sectorNo):
a, b, c, d, x, y, z, t = [0], [0], [0], [0], [0], [0], [0], [0]
dfs_prepare(dfsc, sectorNo, x, y, z, t)
num = [0]
data_list = []
for _d in data:
tmp = struct.pack('L', _d)
data_list.append(struct.unpack('I', tmp[:4])[0])
data_list.append(struct.unpack('I', tmp[4:])[0])
for i in range(4):
dfs_uncrypt3(dfsc, a, b, c, d, x, y, z, t, data_list, num)
dfs_unmixArray(data_list, num)
return data_list, [struct.unpack('L',struct.pack('I', data_list[0]) + struct.pack('I', data_list[1]))[0],
struct.unpack('L',struct.pack('I', data_list[2]) + struct.pack('I', data_list[3]))[0],
struct.unpack('L',struct.pack('I', data_list[4]) + struct.pack('I', data_list[5]))[0],
struct.unpack('L',struct.pack('I', data_list[6]) + struct.pack('I', data_list[7]))[0]]
def GetMainTime():
timer = time.time()
tv_sec = int(timer)
tv_usec = int((timer-tv_sec)*1000000)
get_timestamp = tv_sec<<10 | int((tv_usec<<10)/1000000)
MAIN_TIME = get_timestamp>>16
MAIN_TIME = hex(MAIN_TIME)+'ffff'
return MAIN_TIME
def AddressToHash(address):
fld = b''
_mime2bits = _mime2bits_init()
e=n=0
address_index = 0
for i in range(32):
while True:
c = address[address_index]
address_index+=1
d = _mime2bits[c]
if d&0xC0 == False:
break
e <<= 6
e = np.uint16(e| d)
n += 6
if n>=8:
n-=8
fld += struct.pack('Q',e >> n)[:1]
for i in range(8):
fld+=b'\x00'
return fld
def _mime2bits_init():
bits2mime = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
_mime2bits = [0xFF] * 256
for i in range(64):
_mime2bits[bits2mime[i]] = i
return _mime2bits
def ReadBE32(x):
return (((x & 0xff000000) >> 24) | ((x & 0x00ff0000) >> 8) | ((x & 0x0000ff00) << 8) | ((x & 0x000000ff) << 24))
def WriteBE64x32(x):
return (((x & 0xff00000000000000) >> 24) | ((x & 0x00ff000000000000) >> 8) | ((x & 0x0000ff0000000000) << 8) | ((x & 0x000000ff00000000) << 24) | ((x & 0x00000000ff000000) >> 24) | ((x & 0x0000000000ff0000) >> 8) | ((x & 0x000000000000ff00) << 8) | ((x & 0x00000000000000ff) << 24))
def Ch(x, y, z):
return z ^ (x & (y ^ z))
def Maj(x, y, z):
return (x & y) | (z & (x | y))
def Sigma0(x):
return (x >> 2 | x << 30) ^ (x >> 13 | x << 19) ^ (x >> 22 | x << 10)
def Sigma1(x):
return (x >> 6 | x << 26) ^ (x >> 11 | x << 21) ^ (x >> 25 | x << 7)
def sigma0(x):
return (x >> 7 | x << 25) ^ (x >> 18 | x << 14) ^ (x >> 3)
def sigma1(x):
return (x >> 17 | x << 15) ^ (x >> 19 | x << 13) ^ (x >> 10)
def Round(a, b, c, d, e, f, g, h, k, w):
t1 = h[0] + Sigma1(e[0]) + Ch(e[0], f[0], g[0]) + k[0] + w[0]
t2 = Sigma0(a[0]) + Maj(a[0], b[0], c[0])
d[0] = np.uint32(d[0] + t1)
h[0] = np.uint32(t1 + t2)
def to_half(Buffer):
return [struct.unpack('L',struct.pack('L',Buffer[i*2])[:4] + struct.pack('L',Buffer[i*2+1])[:4])[0] for i in range(len(Buffer)//2)]
def to_double(Buffer):
new_Buffer = []
for s in Buffer:
tmp = struct.pack('L',s)
new_Buffer.append(struct.unpack('I', tmp[:4])[0])
new_Buffer.append(struct.unpack('I', tmp[4:])[0])
return new_Buffer
def sha256_transform(s, chunk):
s = to_half(s)
s = to_double(s)
a, b, c, d, e, f, g, h = [s[0]], [s[1]], [s[2]], [s[3]], [s[4]], [s[5]], [s[6]], [s[7]]
w0 = [ReadBE32(chunk[0])]
w1 = [ReadBE32(chunk[1])]
w2 = [ReadBE32(chunk[2])]
w3 = [ReadBE32(chunk[3])]
w4 = [ReadBE32(chunk[4])]
w5 = [ReadBE32(chunk[5])]
w6 = [ReadBE32(chunk[6])]
w7 = [ReadBE32(chunk[7])]
w8 = [ReadBE32(chunk[8])]
w9 = [ReadBE32(chunk[9])]
w10 = [ReadBE32(chunk[10])]
w11 = [ReadBE32(chunk[11])]
w12 = [ReadBE32(chunk[12])]
w13 = [ReadBE32(chunk[13])]
w14 = [ReadBE32(chunk[14])]
w15 = [ReadBE32(chunk[15])]
Round(a, b, c, d, e, f, g, h, [0x428a2f98], w0)
Round(h, a, b, c, d, e, f, g, [0x71374491], w1)
Round(g, h, a, b, c, d, e, f, [0xb5c0fbcf], w2)
Round(f, g, h, a, b, c, d, e, [0xe9b5dba5], w3)
Round(e, f, g, h, a, b, c, d, [0x3956c25b], w4)
Round(d, e, f, g, h, a, b, c, [0x59f111f1], w5)
Round(c, d, e, f, g, h, a, b, [0x923f82a4], w6)
Round(b, c, d, e, f, g, h, a, [0xab1c5ed5], w7)
Round(a, b, c, d, e, f, g, h, [0xd807aa98], w8)
Round(h, a, b, c, d, e, f, g, [0x12835b01], w9)
Round(g, h, a, b, c, d, e, f, [0x243185be], w10)
Round(f, g, h, a, b, c, d, e, [0x550c7dc3], w11)
Round(e, f, g, h, a, b, c, d, [0x72be5d74], w12)
Round(d, e, f, g, h, a, b, c, [0x80deb1fe], w13)
Round(c, d, e, f, g, h, a, b, [0x9bdc06a7], w14)
Round(b, c, d, e, f, g, h, a, [0xc19bf174], w15)
K = [0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2]
K_index = 0
for i in range(3):
w0[0] = np.uint32(w0[0] + sigma1(w14[0]) + w9[0] + sigma0(w1[0]))
w1[0] = np.uint32(w1[0] + sigma1(w15[0]) + w10[0] + sigma0(w2[0]))
w2[0] = np.uint32(w2[0] + sigma1(w0[0]) + w11[0] + sigma0(w3[0]))
w3[0] = np.uint32(w3[0] + sigma1(w1[0]) + w12[0] + sigma0(w4[0]))
w4[0] = np.uint32(w4[0] + sigma1(w2[0]) + w13[0] + sigma0(w5[0]))
w5[0] = np.uint32(w5[0] + sigma1(w3[0]) + w14[0] + sigma0(w6[0]))
w6[0] = np.uint32(w6[0] + sigma1(w4[0]) + w15[0] + sigma0(w7[0]))
w7[0] = np.uint32(w7[0] + sigma1(w5[0]) + w0[0] + sigma0(w8[0]))
w8[0] = np.uint32(w8[0] + sigma1(w6[0]) + w1[0] + sigma0(w9[0]))
w9[0] = np.uint32(w9[0] + sigma1(w7[0]) + w2[0] + sigma0(w10[0]))
w10[0] = np.uint32(w10[0] + sigma1(w8[0]) + w3[0] + sigma0(w11[0]))
w11[0] = np.uint32(w11[0] + sigma1(w9[0]) + w4[0] + sigma0(w12[0]))
w12[0] = np.uint32(w12[0] + sigma1(w10[0]) + w5[0] + sigma0(w13[0]))
w13[0] = np.uint32(w13[0] + sigma1(w11[0]) + w6[0] + sigma0(w14[0]))
w14[0] = np.uint32(w14[0] + sigma1(w12[0]) + w7[0] + sigma0(w15[0]))
w15[0] = np.uint32(w15[0] + sigma1(w13[0]) + w8[0] + sigma0(w0[0]))
Round(a, b, c, d, e, f, g, h, [K[K_index]], w0);K_index+=1
Round(h, a, b, c, d, e, f, g, [K[K_index]], w1);K_index+=1
Round(g, h, a, b, c, d, e, f, [K[K_index]], w2);K_index+=1
Round(f, g, h, a, b, c, d, e, [K[K_index]], w3);K_index+=1
Round(e, f, g, h, a, b, c, d, [K[K_index]], w4);K_index+=1
Round(d, e, f, g, h, a, b, c, [K[K_index]], w5);K_index+=1
Round(c, d, e, f, g, h, a, b, [K[K_index]], w6);K_index+=1
Round(b, c, d, e, f, g, h, a, [K[K_index]], w7);K_index+=1
Round(a, b, c, d, e, f, g, h, [K[K_index]], w8);K_index+=1
Round(h, a, b, c, d, e, f, g, [K[K_index]], w9);K_index+=1
Round(g, h, a, b, c, d, e, f, [K[K_index]], w10);K_index+=1
Round(f, g, h, a, b, c, d, e, [K[K_index]], w11);K_index+=1
Round(e, f, g, h, a, b, c, d, [K[K_index]], w12);K_index+=1
Round(d, e, f, g, h, a, b, c, [K[K_index]], w13);K_index+=1
Round(c, d, e, f, g, h, a, b, [K[K_index]], w14);K_index+=1
Round(b, c, d, e, f, g, h, a, [K[K_index]], w15);K_index+=1
s[0] += a[0];
s[1] += b[0];
s[2] += c[0];
s[3] += d[0];
s[4] += e[0];
s[5] += f[0];
s[6] += g[0];
s[7] += h[0];
return s
def shasha(state, data, nonce):
stateBuffer = [struct.unpack('I',state[i*4:i*4+4])[0] for i in range(8)]
data = data[:56] + struct.pack('L', nonce)
dataBuffer = [struct.unpack('I',data[i*4:i*4+4])[0] for i in range(16)]
stateBuffer = sha256_transform(stateBuffer, dataBuffer)
dataBuffer[0] = 0x80
dataBuffer[1] = 0
dataBuffer[2] = 0
dataBuffer[3] = 0
dataBuffer[4] = 0
dataBuffer[5] = 0
dataBuffer[6] = 0
dataBuffer[7] = 0
dataBuffer[8] = 0
dataBuffer[9] = 0
dataBuffer[10] = 0
dataBuffer[11] = 0
dataBuffer[12] = 0
dataBuffer[13] = 0
dataBuffer[14] = 0
dataBuffer[15] = 1048576
stateBuffer = sha256_transform(stateBuffer, dataBuffer)
stateBuffer = to_half(stateBuffer)
dataBuffer = to_half(dataBuffer)
for i in range(4):
dataBuffer[i] = WriteBE64x32(stateBuffer[i])
stateBuffer[0] = 0xbb67ae856a09e667
stateBuffer[1] = 0xa54ff53a3c6ef372
stateBuffer[2] = 0x9b05688c510e527f
stateBuffer[3] = 0x5be0cd191f83d9ab
dataBuffer[4] = 0x80
dataBuffer[7] = 0x0001000000000000
new_stateBuffer = to_double(stateBuffer)
new_dataBuffer = to_double(dataBuffer)
stateBuffer = sha256_transform(new_stateBuffer, new_dataBuffer)
stateBuffer = to_half(stateBuffer)
hash = [0,0,0,0]
for i in range(4):
hash[i] = WriteBE64x32(stateBuffer[i])
return hash
def CompareHashes(l, r):
for i in range(3,-1,-1):
if l[i] < r[i]:
return True
elif l[i] > r[i]:
return False
return False
def SearchMinNonce(task_ctx_state, task_ctx_data, nonce):
for i in range(256):
currentHash = shasha(task_ctx_state, task_ctx_data, nonce[0])
if i==0 or CompareHashes(currentHash,hash):
hash = copy.deepcopy(currentHash)
minNonce = nonce[0]
nonce[0] = nonce[0] + 1
return minNonce, hash
def HasNewShare(nonce):
while True:
last_amount, hash = SearchMinNonce(task_ctx_state, task_ctx_data, nonce)
#last_amount, hash = SearchMinNonce(task_ctx_state, task_ctx_data, lastfield_amount)
if CompareHashes(hash,minhash_data):
print ('isShareFound')
return last_amount, hash
print (nonce)
state1, xdag_field_1 = dfslib_uncrypt_array(_c, xdag_field1.data,0)
state2, xdag_field_2 = dfslib_uncrypt_array(_c, xdag_field2.data,1)
state2_list = b''
for s in state2:
tmp = struct.pack('I', s)
state2_list+= tmp
addressHash = AddressToHash(b'gKNRtSL1pUaTpzMuPMznKw49ILtP6qX3')
task_ctx_data = state2_list + addressHash[:24]
task_ctx_state = b''
for s in state1:
tmp = struct.pack('I', s)
task_ctx_state+= tmp
main_time = GetMainTime()
print ('New task:\t',main_time[2:])
print ('State:')
print (task_ctx_state.hex())
print ('Data:')
print (task_ctx_data.hex())
lastfield_amount = random.randint(0, 2**64)
print ('Start nonce:\t', lastfield_amount)
print ('Start minhash:')
minhash_data = [18446744073709551615,18446744073709551615,18446744073709551615,9895604649983]
str_minhash_data = struct.pack('>Q',minhash_data[3])+struct.pack('>Q',minhash_data[2])+struct.pack('>Q',minhash_data[1])+struct.pack('>Q',minhash_data[0])
print (str_minhash_data.hex())
a = struct.unpack('L',addressHash[:8])[0]
b = struct.unpack('L',addressHash[8:16])[0]
c = struct.unpack('L',addressHash[16:24])[0]
d = lastfield_amount
lastfield = xdag_field()
lastfield.transport_header = a
lastfield.type = b
lastfield.time = c
lastfield.hash = [a, b, c]
lastfield.amount = d
lastfield.end_time = d
lastfield.data = [a, b, c, d]
last_amount, hash = HasNewShare([3980675776616400062])
lastfield.amount = last_amount
lastfield.end_time = last_amount
#lastfield.data[3] = last_amount
lastfield.data[3] = 11277376069999640039
def dfs_encrypt2(dfsc, a, b, c, d, x, y, z, t, data, num):
a[0] = np.uint32(dfs_crypt0(dfsc, a, x, y, z, t)) ^ np.uint32(~data[num[0]]); dfs_crypt0(dfsc, b, y, z, t, x)
dfs_crypt0(dfsc, c, z, t, x, y);
data[num[0]] = np.uint32(data[num[0]]) - np.uint32(dfs_crypt0(dfsc, d, t, x, y, z));
num[0] +=1
def dfs_encrypt3(dfsc, a, b, c, d, x, y, z, t, data, num):
dfs_encrypt2(dfsc, a, b, c, d, x, y, z, t, data, num);dfs_encrypt2(dfsc, x, y, z, t, a, b, c, d, data, num)
def dfs_enmix2(c,d, num):
num[0] -=1
d[num[0]] = d[num[0]] ^np.uint32(c[0] * 43385317)
c[0] = d[num[0]]
def dfs_enmixArray(d, num):
c = [1615037507]
for i in range(8):
dfs_enmix2(c, d, num)
def dfslib_encrypt_array(dfsc, data):
a, b, c, d, x, y, z, t = [0], [0], [0], [0], [0], [0], [0], [0]
dfs_prepare(dfsc, 16, x, y, z, t)#sectorNo=16
num = [8]
data = to_double(data)
dfs_enmixArray(data, num)
num = [0]
for i in range(4):
dfs_encrypt3(dfsc, a, b, c, d, x, y, z, t, data, num)
return to_half(data)
fieldsCopy = dfslib_encrypt_array(_c, lastfield.data)
Write = b''
for f in fieldsCopy:
Write += struct.pack('L', f)
print (Write)
print (123)
标签:字节截取 prepare gpu -o 源码 翻译 大量 init 判断
原文地址:http://blog.51cto.com/7366092/2156696