forked from opentimestamps/opentimestamps-client
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcache.py
92 lines (76 loc) · 3.04 KB
/
cache.py
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
# Copyright (C) 2016 The OpenTimestamps developers
#
# This file is part of the OpenTimestamps Client.
#
# It is subject to the license terms in the LICENSE file found in the top-level
# directory of this distribution.
#
# No part of the OpenTimestamps Client including this file, may be copied,
# modified, propagated, or distributed except according to the terms contained
# in the LICENSE file.
import os
from opentimestamps.core.timestamp import Timestamp
from opentimestamps.core.serialize import StreamSerializationContext, StreamDeserializationContext
from bitcoin.core import b2x
class TimestampCache:
"""Persistant cache of timestamps"""
def __init__(self, path):
self.path = path
if path is not None:
# Simple version scheme
try:
with open(self.path + '/version', 'r') as fd:
try:
major, minor = fd.read().strip().split('.')
major = int(major)
minor = int(minor)
if major != 1:
raise Exception
except Exception:
raise Exception("Unknown timestamp cache version")
except FileNotFoundError:
os.makedirs(self.path, exist_ok=True)
with open(self.path + '/version', 'w') as fd:
fd.write('%d.%d\n' % (1,0))
def __commitment_to_filename(self, commitment):
assert len(commitment) >= 20
return (self.path + '/' +
b2x(commitment[0:1]) + '/' +
b2x(commitment[1:2]) + '/' +
b2x(commitment[2:3]) + '/' +
b2x(commitment[3:4]) + '/' +
b2x(commitment))
def __contains__(self, commitment):
try:
self[commitment]
return True
except KeyError:
return False
def __getitem__(self, commitment):
if self.path is None:
raise KeyError
elif len(commitment) > 64: # FIXME: hack to avoid filename-too-long errors
raise KeyError
try:
with open(self.__commitment_to_filename(commitment), 'rb') as stamp_fd:
ctx = StreamDeserializationContext(stamp_fd)
stamp = Timestamp.deserialize(ctx, commitment)
return stamp
except FileNotFoundError:
raise KeyError
def __save(self, timestamp):
if self.path is None:
return
# FIXME: should do this atomically
path = self.__commitment_to_filename(timestamp.msg)
os.makedirs(os.path.dirname(path), exist_ok=True)
with open(self.__commitment_to_filename(timestamp.msg), 'wb') as stamp_fd:
ctx = StreamSerializationContext(stamp_fd)
timestamp.serialize(ctx)
def merge(self, new_timestamp):
try:
existing = self[new_timestamp.msg]
except KeyError:
existing = Timestamp(new_timestamp.msg)
existing.merge(new_timestamp)
self.__save(existing)