@@ -37,49 +37,42 @@ module RSCoin.User.Operations
37
37
, retrieveAllocationsList
38
38
) where
39
39
40
- import Control.Arrow ((***) )
41
- import Control.Exception (SomeException , assert ,
42
- fromException )
43
- import Control.Lens ((^.) )
44
- import Control.Monad (filterM , forM_ , unless , void , when )
45
- import Control.Monad.Catch (MonadThrow , catch , throwM , try )
46
- import Control.Monad.Extra (whenJust )
47
- import Control.Monad.IO.Class (MonadIO , liftIO )
48
- import Control.Monad.State (StateT (.. ), execStateT , get ,
49
- modify )
50
- import Control.Monad.Trans.Class (lift )
51
- import Data.Acid.Advanced (query' , update' )
52
- import Data.Bifunctor (first )
53
- import Data.Function (on )
54
- import qualified Data.IntMap.Strict as I
55
- import Data.List (delete , elemIndex , foldl1' ,
56
- genericIndex , genericLength ,
57
- groupBy , nub , sortOn )
58
- import qualified Data.Map as M
59
- import Data.Maybe (fromJust , fromMaybe , isJust ,
60
- isNothing )
61
- import Data.Monoid ((<>) )
62
- import qualified Data.Set as S
63
- import qualified Data.Text as T
64
- import Data.Text.Buildable (Buildable )
65
- import qualified Data.Text.IO as TIO
66
- import Data.Tuple.Select (sel1 , sel2 , sel3 )
67
- import Formatting (build , int , sformat , shown , (%) )
68
- import Safe (atMay )
69
-
70
- import Serokell.Util (listBuilderJSON ,
71
- listBuilderJSONIndent , pairBuilder )
72
-
73
- import qualified RSCoin.Core as C
74
- import RSCoin.Timed (MonadRpc (getNodeContext ), WorkMode ,
75
- for , sec , wait )
76
- import qualified RSCoin.User.AcidState as A
77
- import RSCoin.User.Cache (UserCache )
78
- import RSCoin.User.Error (UserError (.. ), UserLogicError ,
79
- isWalletSyncError )
80
- import RSCoin.User.Logic (SignatureBundle , getExtraSignatures ,
81
- joinBundles , validateTransaction )
82
- import qualified RSCoin.User.Wallet as W
40
+ import Control.Arrow ((***) )
41
+ import Control.Exception (SomeException , assert , fromException )
42
+ import Control.Lens ((^.) )
43
+ import Control.Monad (filterM , forM_ , unless , void , when )
44
+ import Control.Monad.Catch (MonadThrow , catch , throwM , try )
45
+ import Control.Monad.Extra (whenJust )
46
+ import Control.Monad.IO.Class (MonadIO , liftIO )
47
+ import Data.Acid.Advanced (query' , update' )
48
+ import Data.Function (on )
49
+ import qualified Data.IntMap.Strict as I
50
+ import Data.List (elemIndex , foldl1' , genericIndex ,
51
+ genericLength , groupBy , nub , sortOn )
52
+ import qualified Data.Map as M
53
+ import Data.Maybe (fromJust , fromMaybe , isJust , isNothing )
54
+ import Data.Monoid ((<>) )
55
+ import qualified Data.Text as T
56
+ import Data.Text.Buildable (Buildable )
57
+ import qualified Data.Text.IO as TIO
58
+ import Data.Tuple.Select (sel1 , sel2 , sel3 )
59
+ import Debug.Trace
60
+ import Formatting (build , int , sformat , shown , (%) )
61
+ import Safe (atMay )
62
+
63
+ import Serokell.Util (listBuilderJSON , listBuilderJSONIndent ,
64
+ pairBuilder )
65
+
66
+ import qualified RSCoin.Core as C
67
+ import RSCoin.Timed (MonadRpc (getNodeContext ), WorkMode ,
68
+ for , sec , wait )
69
+ import qualified RSCoin.User.AcidState as A
70
+ import RSCoin.User.Cache (UserCache )
71
+ import RSCoin.User.Error (UserError (.. ), UserLogicError ,
72
+ isWalletSyncError )
73
+ import RSCoin.User.Logic (SignatureBundle , getExtraSignatures ,
74
+ joinBundles , validateTransaction )
75
+ import qualified RSCoin.User.Wallet as W
83
76
84
77
walletInitialized :: MonadIO m => A. RSCoinUserState -> m Bool
85
78
walletInitialized st = query' st A. IsInitialized
@@ -222,13 +215,11 @@ isInitialized st = query' st A.IsInitialized
222
215
addUserAddress
223
216
:: MonadIO m
224
217
=> A. RSCoinUserState
225
- -> Maybe C. SecretKey
226
218
-> C. PublicKey
227
- -> [C. Transaction ]
228
- -> S. Set W. TxHistoryRecord
219
+ -> Maybe C. SecretKey
229
220
-> m ()
230
- addUserAddress st skMaybe pk txs hRecords =
231
- update' st $ A. AddAddress (C. Address pk, skMaybe) txs hRecords
221
+ addUserAddress st pk skMaybe =
222
+ update' st $ A. AddAddress (C. Address pk) skMaybe M. empty
232
223
233
224
-- | Same as addAddress, but queries blockchain automatically and
234
225
-- queries transactions that affect this address
@@ -237,60 +228,47 @@ importAddress
237
228
=> A. RSCoinUserState
238
229
-> (Maybe C. SecretKey , C. PublicKey )
239
230
-> Int
240
- -> Maybe Int
241
231
-> m ()
242
- importAddress st (skMaybe,pk) fromH toH0 = do
232
+ importAddress st (skMaybe,pk) fromH = do
243
233
whenJust skMaybe $ \ sk ->
244
234
unless (C. checkKeyPair (sk,pk)) $
245
235
commitError " The provided pair doesn't match thus can't be used"
246
236
ourSk <- query' st $ A. GetSecretKey $ C. Address pk
247
237
case ourSk of
248
238
Nothing -> return () -- it's ok
249
- Just Nothing -> C. logInfo $ " The address doesn't have secret key, " <>
250
- " adding this one with re-query"
239
+ Just Nothing | isJust skMaybe ->
240
+ C. logInfo $ " The address doesn't have secret key, " <>
241
+ " adding this sk with re-query"
242
+ Just Nothing ->
243
+ commitError " This address doesn't have sk, won't update without provided"
251
244
Just (Just _) -> commitError " The address is already imported"
252
245
when (fromH < 0 ) $ commitError $
253
246
sformat (" Height 'from' " % int % " must be positive!" ) fromH
254
- whenJust toH0 $ \ toH -> do
255
- when (toH < 0 ) $ commitError $
256
- sformat (" Height 'to' " % int % " must be positive!" ) toH
257
- when (toH < fromH) $ commitError $ sformat
258
- (" Height 'from' " % int % " is greater than height 'to' " % int)
259
- fromH toH
260
247
walletHeight <- query' st A. GetLastBlockId
261
- let toH = fromMaybe walletHeight toH0
262
- when (toH > walletHeight) $
263
- let formatPattern = " Desired interval [" % int % " ," % int %
264
- " ] must lie exactly within [0," % int % " ]," %
248
+ when (fromH > walletHeight) $
249
+ let formatPattern =
250
+ " fromH must be exactly within [0," % int % " ]," %
265
251
" where " % int %
266
252
" is current wallet's top known blockchain height."
267
- in commitError $ sformat formatPattern fromH toH walletHeight walletHeight
253
+ in commitError $ sformat formatPattern walletHeight walletHeight
254
+ let period = [fromH.. walletHeight]
255
+ delta = max (walletHeight - fromH - 1 ) $
256
+ max 100 $ (walletHeight - fromH) `div` 10
257
+ periodsLast = splitEvery delta period
258
+ traceM $ " Period is : " ++ show period
259
+ traceM $ " Delta is : " ++ show delta
260
+ traceM $ " periods is : " ++ show periodsLast
268
261
C. logInfo $ sformat
269
- (" Starting blockchain query process for blocks " % int % " .." % int) fromH toH
270
- (txs,txHistoryRecords) <-
271
- execStateT (gatherTransactionsDo [fromH .. toH] ) ([] , S. empty)
262
+ (" Starting blockchain query process for blocks " % int % " .." % int) fromH walletHeight
263
+ hblocks <- (period `zip` ) . concat <$>
264
+ mapM ( \ l -> C. getBlocksByHeight ( head l ) (last l)) periodsLast
272
265
C. logInfo " Ended blockchain query process"
273
- update' st $ A. AddAddress (newAddress,skMaybe)
274
- (nub $ map fst txs) txHistoryRecords
266
+ update' st $ A. AddAddress newAddress skMaybe $ M. fromList hblocks
275
267
where
276
268
newAddress = C. Address pk
277
- gatherTransactionsDo
278
- :: (WorkMode m ) =>
279
- [Int ] -> StateT ([(C. Transaction ,C. AddrId )], S. Set W. TxHistoryRecord ) m ()
280
- gatherTransactionsDo [] = return ()
281
- gatherTransactionsDo (periodId: otherPeriodIds) = do
282
- C. HBlock {.. } <- lift $ C. getBlockByHeight periodId
283
- forM_ hbTransactions $ \ tx ->
284
- W. handleToAdd [newAddress] tx $ \ _ addrid -> do
285
- let histRecord =
286
- W. TxHistoryRecord tx periodId W. TxHConfirmed
287
- $ S. singleton newAddress
288
- modify (((tx,addrid) : ) *** S. insert histRecord)
289
- forM_ hbTransactions $ \ tx -> do
290
- currentTxs <- fst <$> get
291
- toRemove <- W. getToRemove [(newAddress, currentTxs)] tx
292
- forM_ toRemove $ \ (_,pair') -> modify (first $ delete pair')
293
- gatherTransactionsDo otherPeriodIds
269
+ splitEvery _ [] = []
270
+ splitEvery n list = let (first,rest) = splitAt n list
271
+ in first : (splitEvery n rest)
294
272
295
273
-- | Deletes an address. Accepts an index in [0..length addresses)
296
274
deleteUserAddress :: (WorkMode m ) => A. RSCoinUserState -> Int -> m ()
0 commit comments