source file: /home/buildslave/tahoe/edgy/build/src/allmydata/mutable/layout.py
file stats: 124 lines, 123 executed: 99.2% covered
1.
2. import struct
3. from common import NeedMoreDataError
4.
5. PREFIX = ">BQ32s16s" # each version has a different prefix
6. SIGNED_PREFIX = ">BQ32s16s BBQQ" # this is covered by the signature
7. SIGNED_PREFIX_LENGTH = struct.calcsize(SIGNED_PREFIX)
8. HEADER = ">BQ32s16s BBQQ LLLLQQ" # includes offsets
9. HEADER_LENGTH = struct.calcsize(HEADER)
10.
11. def unpack_header(data):
12. o = {}
13. (version,
14. seqnum,
15. root_hash,
16. IV,
17. k, N, segsize, datalen,
18. o['signature'],
19. o['share_hash_chain'],
20. o['block_hash_tree'],
21. o['share_data'],
22. o['enc_privkey'],
23. o['EOF']) = struct.unpack(HEADER, data[:HEADER_LENGTH])
24. return (version, seqnum, root_hash, IV, k, N, segsize, datalen, o)
25.
26. def unpack_prefix_and_signature(data):
27. assert len(data) >= HEADER_LENGTH, len(data)
28. prefix = data[:SIGNED_PREFIX_LENGTH]
29.
30. (version,
31. seqnum,
32. root_hash,
33. IV,
34. k, N, segsize, datalen,
35. o) = unpack_header(data)
36.
37. assert version == 0
38. if len(data) < o['share_hash_chain']:
39. raise NeedMoreDataError(o['share_hash_chain'],
40. o['enc_privkey'], o['EOF']-o['enc_privkey'])
41.
42. pubkey_s = data[HEADER_LENGTH:o['signature']]
43. signature = data[o['signature']:o['share_hash_chain']]
44.
45. return (seqnum, root_hash, IV, k, N, segsize, datalen,
46. pubkey_s, signature, prefix)
47.
48. def unpack_share(data):
49. assert len(data) >= HEADER_LENGTH
50. o = {}
51. (version,
52. seqnum,
53. root_hash,
54. IV,
55. k, N, segsize, datalen,
56. o['signature'],
57. o['share_hash_chain'],
58. o['block_hash_tree'],
59. o['share_data'],
60. o['enc_privkey'],
61. o['EOF']) = struct.unpack(HEADER, data[:HEADER_LENGTH])
62.
63. assert version == 0
64. if len(data) < o['EOF']:
65. raise NeedMoreDataError(o['EOF'],
66. o['enc_privkey'], o['EOF']-o['enc_privkey'])
67.
68. pubkey = data[HEADER_LENGTH:o['signature']]
69. signature = data[o['signature']:o['share_hash_chain']]
70. share_hash_chain_s = data[o['share_hash_chain']:o['block_hash_tree']]
71. share_hash_format = ">H32s"
72. hsize = struct.calcsize(share_hash_format)
73. assert len(share_hash_chain_s) % hsize == 0, len(share_hash_chain_s)
74. share_hash_chain = []
75. for i in range(0, len(share_hash_chain_s), hsize):
76. chunk = share_hash_chain_s[i:i+hsize]
77. (hid, h) = struct.unpack(share_hash_format, chunk)
78. share_hash_chain.append( (hid, h) )
79. share_hash_chain = dict(share_hash_chain)
80. block_hash_tree_s = data[o['block_hash_tree']:o['share_data']]
81. assert len(block_hash_tree_s) % 32 == 0, len(block_hash_tree_s)
82. block_hash_tree = []
83. for i in range(0, len(block_hash_tree_s), 32):
84. block_hash_tree.append(block_hash_tree_s[i:i+32])
85.
86. share_data = data[o['share_data']:o['enc_privkey']]
87. enc_privkey = data[o['enc_privkey']:o['EOF']]
88.
89. return (seqnum, root_hash, IV, k, N, segsize, datalen,
90. pubkey, signature, share_hash_chain, block_hash_tree,
91. share_data, enc_privkey)
92.
93. def unpack_share_data(verinfo, hash_and_data):
94. (seqnum, root_hash, IV, segsize, datalength, k, N, prefix, o_t) = verinfo
95.
96. # hash_and_data starts with the share_hash_chain, so figure out what the
97. # offsets really are
98. o = dict(o_t)
99. o_share_hash_chain = 0
100. o_block_hash_tree = o['block_hash_tree'] - o['share_hash_chain']
101. o_share_data = o['share_data'] - o['share_hash_chain']
102. o_enc_privkey = o['enc_privkey'] - o['share_hash_chain']
103.
104. share_hash_chain_s = hash_and_data[o_share_hash_chain:o_block_hash_tree]
105. share_hash_format = ">H32s"
106. hsize = struct.calcsize(share_hash_format)
107. assert len(share_hash_chain_s) % hsize == 0, len(share_hash_chain_s)
108. share_hash_chain = []
109. for i in range(0, len(share_hash_chain_s), hsize):
110. chunk = share_hash_chain_s[i:i+hsize]
111. (hid, h) = struct.unpack(share_hash_format, chunk)
112. share_hash_chain.append( (hid, h) )
113. share_hash_chain = dict(share_hash_chain)
114. block_hash_tree_s = hash_and_data[o_block_hash_tree:o_share_data]
115. assert len(block_hash_tree_s) % 32 == 0, len(block_hash_tree_s)
116. block_hash_tree = []
117. for i in range(0, len(block_hash_tree_s), 32):
118. block_hash_tree.append(block_hash_tree_s[i:i+32])
119.
120. share_data = hash_and_data[o_share_data:o_enc_privkey]
121.
122. return (share_hash_chain, block_hash_tree, share_data)
123.
124.
125. def pack_checkstring(seqnum, root_hash, IV):
126. return struct.pack(PREFIX,
127. 0, # version,
128. seqnum,
129. root_hash,
130. IV)
131.
132. def unpack_checkstring(checkstring):
133. cs_len = struct.calcsize(PREFIX)
134. version, seqnum, root_hash, IV = struct.unpack(PREFIX, checkstring[:cs_len])
135. assert version == 0 # TODO: just ignore the share
136. return (seqnum, root_hash, IV)
137.
138. def pack_prefix(seqnum, root_hash, IV,
139. required_shares, total_shares,
140. segment_size, data_length):
141. prefix = struct.pack(SIGNED_PREFIX,
142. 0, # version,
143. seqnum,
144. root_hash,
145. IV,
146.
147. required_shares,
148. total_shares,
149. segment_size,
150. data_length,
151. )
152. return prefix
153.
154. def pack_offsets(verification_key_length, signature_length,
155. share_hash_chain_length, block_hash_tree_length,
156. share_data_length, encprivkey_length):
157. post_offset = HEADER_LENGTH
158. offsets = {}
159. o1 = offsets['signature'] = post_offset + verification_key_length
160. o2 = offsets['share_hash_chain'] = o1 + signature_length
161. o3 = offsets['block_hash_tree'] = o2 + share_hash_chain_length
162. o4 = offsets['share_data'] = o3 + block_hash_tree_length
163. o5 = offsets['enc_privkey'] = o4 + share_data_length
164. o6 = offsets['EOF'] = o5 + encprivkey_length
165.
166. return struct.pack(">LLLLQQ",
167. offsets['signature'],
168. offsets['share_hash_chain'],
169. offsets['block_hash_tree'],
170. offsets['share_data'],
171. offsets['enc_privkey'],
172. offsets['EOF'])
173.
174. def pack_share(prefix, verification_key, signature,
175. share_hash_chain, block_hash_tree,
176. share_data, encprivkey):
177. share_hash_chain_s = "".join([struct.pack(">H32s", i, share_hash_chain[i])
178. for i in sorted(share_hash_chain.keys())])
179. for h in block_hash_tree:
180. assert len(h) == 32
181. block_hash_tree_s = "".join(block_hash_tree)
182.
183. offsets = pack_offsets(len(verification_key),
184. len(signature),
185. len(share_hash_chain_s),
186. len(block_hash_tree_s),
187. len(share_data),
188. len(encprivkey))
189. final_share = "".join([prefix,
190. offsets,
191. verification_key,
192. signature,
193. share_hash_chain_s,
194. block_hash_tree_s,
195. share_data,
196. encprivkey])
197. return final_share
198.