2323logger = logging .getLogger ("transactions" )
2424
2525class Transaction (Wrapper ):
26- def __init__ (self , type , pgp_fingerprint , message = '' ):
26+ def __init__ (self , type , pgp_fingerprint , message = '' , peering = None ):
2727 self .pgp_fingerprint = pgp_fingerprint
2828 self .message = message
2929 self .type = type
3030 self .error = None
31+ self .peering = peering
3132
3233 def __call__ (self ):
3334 try :
@@ -37,6 +38,7 @@ def __call__(self):
3738
3839 context_data = {}
3940 context_data .update (settings )
41+ context_data .update (self .peering if self .peering else ucg .Peering ().get ())
4042 context_data ['version' ] = 1
4143 context_data ['number' ] = 0 if not last_tx else last_tx ['transaction' ]['number' ]+ 1
4244 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):
5456
5557 if last_tx : tx += "PreviousHash: %(previousHash)s\n " % context_data
5658
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
5864
5965 tx += """\
6066 Comment:
@@ -64,8 +70,6 @@ def __call__(self):
6470 tx = tx .replace ("\n " , "\r \n " )
6571 txs = settings ['gpg' ].sign (tx , detach = True )
6672
67- if self .error : return False
68-
6973 return self .process (tx , txs )
7074
7175 def get_context_data (self ):
@@ -87,6 +91,29 @@ def process(self, tx, txs):
8791
8892 return False
8993
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+
90117class Transfer (Transaction ):
91118 def __init__ (self , pgp_fingerprint , recipient , coins , message = '' ):
92119 super ().__init__ ('TRANSFER' , pgp_fingerprint , message )
@@ -162,31 +189,36 @@ def __init__(self, pgp_fingerprint, coins, message=''):
162189 self .coins = coins
163190
164191 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 ))
166194
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
173197
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
178199
179- m = re . match ( r'^(\d)(0*)$' , str ( __sum ))
200+ return tx
180201
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
184207
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 )
187211
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
191223
192224 return tx
0 commit comments