23
23
logger = logging .getLogger ("transactions" )
24
24
25
25
class Transaction (Wrapper ):
26
- def __init__ (self , type , pgp_fingerprint , message = '' ):
26
+ def __init__ (self , type , pgp_fingerprint , message = '' , peering = None ):
27
27
self .pgp_fingerprint = pgp_fingerprint
28
28
self .message = message
29
29
self .type = type
30
30
self .error = None
31
+ self .peering = peering
31
32
32
33
def __call__ (self ):
33
34
try :
@@ -37,6 +38,7 @@ def __call__(self):
37
38
38
39
context_data = {}
39
40
context_data .update (settings )
41
+ context_data .update (self .peering if self .peering else ucg .Peering ().get ())
40
42
context_data ['version' ] = 1
41
43
context_data ['number' ] = 0 if not last_tx else last_tx ['transaction' ]['number' ]+ 1
42
44
context_data ['previousHash' ] = hashlib .sha1 (("%(raw)s%(signature)s" % last_tx ).encode ('ascii' )).hexdigest ().upper () if last_tx else None
@@ -54,7 +56,11 @@ def __call__(self):
54
56
55
57
if last_tx : tx += "PreviousHash: %(previousHash)s\n " % context_data
56
58
57
- tx += self .get_message (context_data )
59
+ try :
60
+ tx += self .get_message (context_data )
61
+ except ValueError as e :
62
+ self .error = e
63
+ return False
58
64
59
65
tx += """\
60
66
Comment:
@@ -64,8 +70,6 @@ def __call__(self):
64
70
tx = tx .replace ("\n " , "\r \n " )
65
71
txs = settings ['gpg' ].sign (tx , detach = True )
66
72
67
- if self .error : return False
68
-
69
73
return self .process (tx , txs )
70
74
71
75
def get_context_data (self ):
@@ -87,6 +91,29 @@ def process(self, tx, txs):
87
91
88
92
return False
89
93
94
+ def parse_coins (self , coins_message ):
95
+ coins = []
96
+ for coin in coins_message .split (',' ):
97
+ data = coin .split (':' )
98
+ issuer , numbers = data [0 ], data [1 :]
99
+ for number in numbers :
100
+ view = hdc .coins .View (issuer , int (number )).get ()
101
+ if view ['owner' ] != self .pgp_fingerprint :
102
+ raise ValueError ('Trying to divide a coin you do not own (%s)' % view ['id' ])
103
+ coins .append (view )
104
+ return coins
105
+
106
+ def get_coins_sum (self , coins ):
107
+ __sum = 0
108
+ for coin in coins :
109
+ base , power = coin ['id' ].split ('-' )[2 :4 ]
110
+ __sum += int (base ) * 10 ** int (power )
111
+ return __sum
112
+
113
+ def check_coins_sum (self , __sum ):
114
+ m = re .match (r'^(\d)(0*)$' , str (__sum ))
115
+ if not m : raise ValueError ('bad sum value %d' % __sum )
116
+
90
117
class Transfer (Transaction ):
91
118
def __init__ (self , pgp_fingerprint , recipient , coins , message = '' ):
92
119
super ().__init__ ('TRANSFER' , pgp_fingerprint , message )
@@ -162,31 +189,36 @@ def __init__(self, pgp_fingerprint, coins, message=''):
162
189
self .coins = coins
163
190
164
191
def get_mono_message (self , context_data , tx = '' ):
165
- context_data ['coins' ] = self .coins
192
+ coins = self .parse_coins (self .coins )
193
+ self .check_coins_sum (self .get_coins_sum (coins ))
166
194
167
- coins = []
168
- for coin in context_data ['coins' ].split (',' ):
169
- data = coin .split (':' )
170
- issuer , numbers = data [0 ], data [1 :]
171
- for number in numbers :
172
- coins .append (ucoin .hdc .coins .View (issuer , int (number )).get ())
195
+ context_data ['base' ], context_data ['power' ] = int (m .groups ()[0 ]), len (m .groups ()[1 ])
196
+ tx += '%(fingerprint)s-%(previous_idx)d-%(base)d-%(power)d-F-%(number)d\n ' % context_data
173
197
174
- __sum = 0
175
- for coin in coins :
176
- base , power = coin ['id' ].split ('-' )[2 :4 ]
177
- __sum += int (base ) * 10 ** int (power )
198
+ for coin in self .old_coins : tx += '%(id)s, %(transaction)s\n ' % coin
178
199
179
- m = re . match ( r'^(\d)(0*)$' , str ( __sum ))
200
+ return tx
180
201
181
- if not m :
182
- self .error = 'bad sum value %d' % __sum
183
- return tx
202
+ class Divide (MonoTransaction ):
203
+ def __init__ (self , pgp_fingerprint , old_coins , new_coins , message = '' ):
204
+ super ().__init__ ('DIVISION' , pgp_fingerprint , message )
205
+ self .old_coins = old_coins
206
+ self .new_coins = new_coins
184
207
185
- context_data ['base' ], context_data ['power' ] = int (m .groups ()[0 ]), len (m .groups ()[1 ])
186
- tx += '%(fingerprint)s-%(previous_idx)d-%(base)d-%(power)d-F-%(number)d\n ' % context_data
208
+ def get_mono_message (self , context_data , tx = '' ):
209
+ old_coins = self .parse_coins (self .old_coins )
210
+ old_coins_sum = self .get_coins_sum (old_coins )
187
211
188
- for coin in coins :
189
- context_data .update (coin )
190
- tx += '%(id)s, %(transaction)s\n ' % context_data
212
+ new_coins_sum = 0
213
+ for idx , coin in enumerate (self .new_coins ):
214
+ context_data ['idx' ] = idx + context_data ['previous_idx' ]
215
+ context_data ['base' ], context_data ['power' ] = [int (x ) for x in coin .split (',' )]
216
+ new_coins_sum += context_data ['base' ] * 10 ** context_data ['power' ]
217
+ tx += '%(fingerprint)s-%(idx)d-%(base)d-%(power)d-D-%(number)d\n ' % context_data
218
+
219
+ if old_coins_sum != new_coins_sum :
220
+ raise ValueError ('Amount of old coins (%d) is not equal to new coins (%d)' % (old_coins_sum , new_coins_sum ))
221
+
222
+ for coin in self .old_coins : tx += '%(id)s, %(transaction)s\n ' % coin
191
223
192
224
return tx
0 commit comments