UFRMWallet.pas 72 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044
  1. unit UFRMWallet;
  2. {$IFDEF FPC}
  3. {$MODE Delphi}
  4. {$ENDIF}
  5. { Copyright (c) 2016 by Albert Molina
  6. Distributed under the MIT software license, see the accompanying file LICENSE
  7. or visit http://www.opensource.org/licenses/mit-license.php.
  8. This unit is a part of Pascal Coin, a P2P crypto currency without need of
  9. historical operations.
  10. If you like it, consider a donation using BitCoin:
  11. 16K3HCZRhFUtM8GdWRcfKeaa6KsuyxZaYk
  12. }
  13. interface
  14. {$I ../config.inc}
  15. uses
  16. {$IFnDEF FPC}
  17. pngimage, Windows, AppEvnts, ShlObj,
  18. {$ELSE}
  19. LCLIntf, LCLType, LMessages,
  20. {$ENDIF}
  21. Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs,
  22. ExtCtrls, ComCtrls, UWallet, StdCtrls, ULog, Grids, UAppParams, UBlockChain,
  23. UNode, UGridUtils, UJSONFunctions, UAccounts, Menus, ImgList, UNetProtocol,
  24. UCrypto, Buttons, UPoolMining, URPC, UFRMAccountSelect, UFRMRPCCalls, UConst,
  25. UTxMultiOperation;
  26. Const
  27. CM_PC_WalletKeysChanged = WM_USER + 1;
  28. CM_PC_NetConnectionUpdated = WM_USER + 2;
  29. type
  30. TMinerPrivateKey = (mpk_NewEachTime, mpk_Random, mpk_Selected);
  31. { TFRMWallet }
  32. TFRMWallet = class(TForm)
  33. cbHashRateUnits: TComboBox;
  34. ebHashRateBackBlocks: TEdit;
  35. lblHashRateBackBlocks: TLabel;
  36. lblHashRateBackBlocks1: TLabel;
  37. MiRPCCalls: TMenuItem;
  38. pnlTop: TPanel;
  39. Image1: TImage;
  40. sbSearchAccount: TSpeedButton;
  41. StatusBar: TStatusBar;
  42. PageControl: TPageControl;
  43. tsMyAccounts: TTabSheet;
  44. tsOperations: TTabSheet;
  45. TrayIcon: TTrayIcon;
  46. TimerUpdateStatus: TTimer;
  47. tsLogs: TTabSheet;
  48. pnlTopLogs: TPanel;
  49. cbShowDebugLogs: TCheckBox;
  50. memoLogs: TMemo;
  51. pnlMyAccountsTop: TPanel;
  52. dgAccounts: TDrawGrid;
  53. cbMyPrivateKeys: TComboBox;
  54. Splitter1: TSplitter;
  55. MainMenu: TMainMenu;
  56. miProject: TMenuItem;
  57. miOptions: TMenuItem;
  58. miPrivatekeys: TMenuItem;
  59. miN1: TMenuItem;
  60. miAbout: TMenuItem;
  61. miAboutPascalCoin: TMenuItem;
  62. miNewOperation: TMenuItem;
  63. Panel1: TPanel;
  64. Label2: TLabel;
  65. ebFilterOperationsStartBlock: TEdit;
  66. ebFilterOperationsEndBlock: TEdit;
  67. tsNodeStats: TTabSheet;
  68. memoNetConnections: TMemo;
  69. memoNetServers: TMemo;
  70. memoNetBlackLists: TMemo;
  71. Label3: TLabel;
  72. Label6: TLabel;
  73. Label7: TLabel;
  74. lblCurrentBlockCaption: TLabel;
  75. lblCurrentBlock: TLabel;
  76. lblCurrentBlockTimeCaption: TLabel;
  77. lblCurrentBlockTime: TLabel;
  78. lblOperationsPendingCaption: TLabel;
  79. lblOperationsPending: TLabel;
  80. lblMiningStatusCaption: TLabel;
  81. lblMinersClients: TLabel;
  82. lblCurrentDifficultyCaption: TLabel;
  83. lblCurrentDifficulty: TLabel;
  84. lblTimeAverage: TLabel;
  85. Label4: TLabel;
  86. tsBlockChain: TTabSheet;
  87. Panel2: TPanel;
  88. Label9: TLabel;
  89. ebBlockChainBlockStart: TEdit;
  90. ebBlockChainBlockEnd: TEdit;
  91. Label8: TLabel;
  92. lblNodeStatus: TLabel;
  93. tsPendingOperations: TTabSheet;
  94. dgPendingOperations: TDrawGrid;
  95. pnlPendingOperations: TPanel;
  96. Label10: TLabel;
  97. cbExploreMyAccounts: TCheckBox;
  98. N1: TMenuItem;
  99. MiClose: TMenuItem;
  100. MiDecodePayload: TMenuItem;
  101. ImageListIcons: TImageList;
  102. ApplicationEvents: {$IFDEF FPC}TApplicationProperties{$ELSE}TApplicationEvents{$ENDIF};
  103. Label5: TLabel;
  104. lblCurrentAccounts: TLabel;
  105. lblTimeAverageAux: TLabel;
  106. tsMessages: TTabSheet;
  107. lbNetConnections: TListBox;
  108. bbSendAMessage: TButton;
  109. Label11: TLabel;
  110. memoMessages: TMemo;
  111. memoMessageToSend: TMemo;
  112. Label12: TLabel;
  113. Label13: TLabel;
  114. Label14: TLabel;
  115. Label16: TLabel;
  116. lblBlocksFound: TLabel;
  117. pnlAccounts: TPanel;
  118. pnlAccountsInfo: TPanel;
  119. Label17: TLabel;
  120. Label19: TLabel;
  121. lblAccountsCount: TLabel;
  122. lblAccountsBalance: TLabel;
  123. lblReceivedMessages: TLabel;
  124. lblBuild: TLabel;
  125. ebFindAccountNumber: TEdit;
  126. Label18: TLabel;
  127. IPnodes1: TMenuItem;
  128. bbChangeKeyName: TBitBtn;
  129. pcAccountsOptions: TPageControl;
  130. tsAccountOperations: TTabSheet;
  131. dgAccountOperations: TDrawGrid;
  132. tsMultiSelectAccounts: TTabSheet;
  133. dgSelectedAccounts: TDrawGrid;
  134. pnlSelectedAccountsTop: TPanel;
  135. pnlSelectedAccountsBottom: TPanel;
  136. pnlSelectedAccountsLeft: TPanel;
  137. sbSelectedAccountsAdd: TSpeedButton;
  138. sbSelectedAccountsAddAll: TSpeedButton;
  139. sbSelectedAccountsDel: TSpeedButton;
  140. sbSelectedAccountsDelAll: TSpeedButton;
  141. Label20: TLabel;
  142. lblSelectedAccountsCount: TLabel;
  143. Label22: TLabel;
  144. lblSelectedAccountsBalance: TLabel;
  145. bbSelectedAccountsOperation: TBitBtn;
  146. Label15: TLabel;
  147. MiOperations: TMenuItem;
  148. MiAddaccounttoSelected: TMenuItem;
  149. MiRemoveaccountfromselected: TMenuItem;
  150. N2: TMenuItem;
  151. MiMultiaccountoperation: TMenuItem;
  152. N3: TMenuItem;
  153. MiFindnextaccountwithhighbalance: TMenuItem;
  154. MiFindpreviousaccountwithhighbalance: TMenuItem;
  155. MiFindaccount: TMenuItem;
  156. cbFilterAccounts: TCheckBox;
  157. ebFilterAccountByBalanceMin: TEdit;
  158. ebFilterAccountByBalanceMax: TEdit;
  159. bbAccountsRefresh: TBitBtn;
  160. dgBlockChainExplorer: TDrawGrid;
  161. dgOperationsExplorer: TDrawGrid;
  162. MiFindOperationbyOpHash: TMenuItem;
  163. MiAccountInformation: TMenuItem;
  164. MiOperationsExplorer: TMenuItem;
  165. procedure cbHashRateUnitsClick(Sender: TObject);
  166. procedure ebHashRateBackBlocksExit(Sender: TObject);
  167. procedure ebHashRateBackBlocksKeyPress(Sender: TObject; var Key: char);
  168. procedure FormCreate(Sender: TObject);
  169. procedure FormDestroy(Sender: TObject);
  170. procedure MiOperationsExplorerClick(Sender: TObject);
  171. procedure MiRPCCallsClick(Sender: TObject);
  172. procedure sbSearchAccountClick(Sender: TObject);
  173. procedure TimerUpdateStatusTimer(Sender: TObject);
  174. procedure cbMyPrivateKeysChange(Sender: TObject);
  175. procedure dgAccountsClick(Sender: TObject);
  176. procedure miOptionsClick(Sender: TObject);
  177. procedure miAboutPascalCoinClick(Sender: TObject);
  178. procedure miNewOperationClick(Sender: TObject);
  179. procedure miPrivatekeysClick(Sender: TObject);
  180. procedure dgAccountsColumnMoved(Sender: TObject; FromIndex,
  181. ToIndex: Integer);
  182. procedure dgAccountsFixedCellClick(Sender: TObject; ACol, ARow: Integer);
  183. procedure PageControlChange(Sender: TObject);
  184. procedure ebFilterOperationsAccountExit(Sender: TObject);
  185. procedure ebFilterOperationsAccountKeyPress(Sender: TObject; var Key: Char);
  186. procedure ebBlockChainBlockStartExit(Sender: TObject);
  187. procedure ebBlockChainBlockStartKeyPress(Sender: TObject; var Key: Char);
  188. procedure cbExploreMyAccountsClick(Sender: TObject);
  189. procedure MiCloseClick(Sender: TObject);
  190. procedure MiDecodePayloadClick(Sender: TObject);
  191. procedure TrayIconDblClick(Sender: TObject);
  192. procedure ApplicationEventsMinimize(Sender: TObject);
  193. procedure bbSendAMessageClick(Sender: TObject);
  194. procedure lblReceivedMessagesClick(Sender: TObject);
  195. procedure ebFindAccountNumberChange(Sender: TObject);
  196. procedure ebFindAccountNumberExit(Sender: TObject);
  197. procedure IPnodes1Click(Sender: TObject);
  198. procedure bbChangeKeyNameClick(Sender: TObject);
  199. procedure sbSelectedAccountsAddClick(Sender: TObject);
  200. procedure sbSelectedAccountsAddAllClick(Sender: TObject);
  201. procedure sbSelectedAccountsDelClick(Sender: TObject);
  202. procedure sbSelectedAccountsDelAllClick(Sender: TObject);
  203. procedure bbSelectedAccountsOperationClick(Sender: TObject);
  204. procedure MiAddaccounttoSelectedClick(Sender: TObject);
  205. procedure MiRemoveaccountfromselectedClick(Sender: TObject);
  206. procedure MiMultiaccountoperationClick(Sender: TObject);
  207. procedure MiFindnextaccountwithhighbalanceClick(Sender: TObject);
  208. procedure MiFindpreviousaccountwithhighbalanceClick(Sender: TObject);
  209. procedure MiFindaccountClick(Sender: TObject);
  210. procedure bbAccountsRefreshClick(Sender: TObject);
  211. procedure ebFilterAccountByBalanceMinExit(Sender: TObject);
  212. procedure ebFilterAccountByBalanceMinKeyPress(Sender: TObject;
  213. var Key: Char);
  214. procedure cbFilterAccountsClick(Sender: TObject);
  215. procedure MiFindOperationbyOpHashClick(Sender: TObject);
  216. procedure MiAccountInformationClick(Sender: TObject);
  217. private
  218. FLastNodesCacheUpdatedTS : TDateTime;
  219. FBackgroundPanel : TPanel;
  220. FMinersBlocksFound: Integer;
  221. procedure SetMinersBlocksFound(const Value: Integer);
  222. Procedure CheckIsReady;
  223. Procedure FinishedLoadingApp;
  224. Procedure FillAccountInformation(Const Strings : TStrings; Const AccountNumber : Cardinal);
  225. Procedure FillOperationInformation(Const Strings : TStrings; Const OperationResume : TOperationResume);
  226. protected
  227. { Private declarations }
  228. FNode : TNode;
  229. FIsActivated : Boolean;
  230. FWalletKeys : TWalletKeysExt;
  231. FLog : TLog;
  232. FAppParams : TAppParams;
  233. FNodeNotifyEvents : TNodeNotifyEvents;
  234. FAccountsGrid : TAccountsGrid;
  235. FSelectedAccountsGrid : TAccountsGrid;
  236. FOperationsAccountGrid : TOperationsGrid;
  237. FPendingOperationsGrid : TOperationsGrid;
  238. FOrderedAccountsKeyList : TOrderedAccountKeysList;
  239. FOperationsExplorerGrid : TOperationsGrid;
  240. FBlockChainGrid : TBlockChainGrid;
  241. FMinerPrivateKeyType : TMinerPrivateKey;
  242. FUpdating : Boolean;
  243. FMessagesUnreadCount : Integer;
  244. FMinAccountBalance : Int64;
  245. FMaxAccountBalance : Int64;
  246. FPoolMiningServer : TPoolMiningServer;
  247. FRPCServer : TRPCServer;
  248. FMustProcessWalletChanged : Boolean;
  249. FMustProcessNetConnectionUpdated : Boolean;
  250. Procedure OnNewAccount(Sender : TObject);
  251. Procedure OnReceivedHelloMessage(Sender : TObject);
  252. Procedure OnNetStatisticsChanged(Sender : TObject);
  253. procedure OnNewLog(logtype : TLogType; Time : TDateTime; ThreadID : TThreadID; Const sender, logtext : AnsiString);
  254. procedure OnWalletChanged(Sender : TObject);
  255. procedure OnNetConnectionsUpdated(Sender : TObject);
  256. procedure OnNetNodeServersUpdated(Sender : TObject);
  257. procedure OnNetBlackListUpdated(Sender : TObject);
  258. Procedure OnNodeMessageEvent(NetConnection : TNetConnection; MessageData : TRawBytes);
  259. Procedure OnSelectedAccountsGridUpdated(Sender : TObject);
  260. Procedure OnMiningServerNewBlockFound(Sender : TObject);
  261. Procedure UpdateConnectionStatus;
  262. Procedure UpdateAccounts(RefreshData : Boolean);
  263. Procedure UpdateBlockChainState;
  264. Procedure UpdatePrivateKeys;
  265. Procedure UpdateOperations;
  266. Procedure LoadAppParams;
  267. Procedure SaveAppParams;
  268. Procedure UpdateConfigChanged;
  269. Procedure UpdateNodeStatus;
  270. Procedure UpdateAvailableConnections;
  271. procedure Activate; override;
  272. Function ForceMining : Boolean; virtual;
  273. Function GetAccountKeyForMiner : TAccountKey;
  274. Procedure DoUpdateAccounts;
  275. Function DoUpdateAccountsFilter : Boolean;
  276. procedure CM_WalletChanged(var Msg: TMessage); message CM_PC_WalletKeysChanged;
  277. procedure CM_NetConnectionUpdated(var Msg: TMessage); message CM_PC_NetConnectionUpdated;
  278. public
  279. { Public declarations }
  280. Property WalletKeys : TWalletKeysExt read FWalletKeys;
  281. Property MinersBlocksFound : Integer read FMinersBlocksFound write SetMinersBlocksFound;
  282. end;
  283. var
  284. FRMWallet: TFRMWallet;
  285. implementation
  286. {$IFnDEF FPC}
  287. {$R *.dfm}
  288. {$ELSE}
  289. {$R *.lfm}
  290. {$ENDIF}
  291. Uses UFolderHelper, UOpenSSL, UOpenSSLdef, UTime, UFileStorage,
  292. UThread, UOpTransaction, UECIES, UFRMPascalCoinWalletConfig,
  293. UFRMOperationsExplorer,
  294. UFRMAbout, UFRMOperation, UFRMWalletKeys, UFRMPayloadDecoder, UFRMNodesIp, UFRMMemoText, USettings;
  295. Type
  296. TThreadActivate = Class(TPCThread)
  297. protected
  298. procedure BCExecute; override;
  299. End;
  300. { TThreadActivate }
  301. procedure TThreadActivate.BCExecute;
  302. begin
  303. // Read Operations saved from disk
  304. TNode.Node.InitSafeboxAndOperations; // New Build 2.1.4 to load pending operations buffer
  305. TNode.Node.AutoDiscoverNodes(CT_Discover_IPs);
  306. TNode.Node.NetServer.Active := true;
  307. Synchronize( FRMWallet.DoUpdateAccounts );
  308. Synchronize( FRMWallet.FinishedLoadingApp );
  309. end;
  310. { TFRMWallet }
  311. procedure TFRMWallet.Activate;
  312. Var ips : AnsiString;
  313. nsarr : TNodeServerAddressArray;
  314. begin
  315. inherited;
  316. if FIsActivated then exit;
  317. FIsActivated := true;
  318. try
  319. // Check OpenSSL dll
  320. if Not LoadSSLCrypt then raise Exception.Create('Cannot load '+SSL_C_LIB+#10+'To use this software make sure this file is available on you system or reinstall the application');
  321. TCrypto.InitCrypto;
  322. // Read Wallet
  323. Try
  324. FWalletKeys.WalletFileName := TFolderHelper.GetPascalCoinDataFolder+PathDelim+'WalletKeys.dat';
  325. Except
  326. On E:Exception do begin
  327. E.Message := 'Cannot open your wallet... Perhaps another instance of Pascal Coin is active!'+#10+#10+E.Message;
  328. Raise;
  329. end;
  330. End;
  331. ips := FAppParams.ParamByName[CT_PARAM_TryToConnectOnlyWithThisFixedServers].GetAsString('');
  332. TNode.DecodeIpStringToNodeServerAddressArray(ips,nsarr);
  333. TNetData.NetData.DiscoverFixedServersOnly(nsarr);
  334. setlength(nsarr,0);
  335. // Creating Node:
  336. FNode := TNode.Node;
  337. FNode.NetServer.Port := FAppParams.ParamByName[CT_PARAM_InternetServerPort].GetAsInteger(CT_NetServer_Port);
  338. FNode.PeerCache := FAppParams.ParamByName[CT_PARAM_PeerCache].GetAsString('')+';'+CT_Discover_IPs;
  339. // Create RPC server
  340. FRPCServer := TRPCServer.Create;
  341. FRPCServer.WalletKeys := WalletKeys;
  342. FRPCServer.Active := FAppParams.ParamByName[CT_PARAM_JSONRPCEnabled].GetAsBoolean(false);
  343. FRPCServer.ValidIPs := FAppParams.ParamByName[CT_PARAM_JSONRPCAllowedIPs].GetAsString('127.0.0.1');
  344. WalletKeys.SafeBox := FNode.Bank.SafeBox;
  345. // Check Database
  346. FNode.Bank.StorageClass := TFileStorage;
  347. TFileStorage(FNode.Bank.Storage).DatabaseFolder := TFolderHelper.GetPascalCoinDataFolder+PathDelim+'Data';
  348. TFileStorage(FNode.Bank.Storage).Initialize;
  349. // Init Grid
  350. //FAccountsGrid.Node := FNode;
  351. FSelectedAccountsGrid.Node := FNode;
  352. FWalletKeys.OnChanged.Add( OnWalletChanged );
  353. FAccountsGrid.Node := FNode;
  354. FOperationsAccountGrid.Node := FNode;
  355. // Reading database
  356. TThreadActivate.Create(false).FreeOnTerminate := true;
  357. FNodeNotifyEvents.Node := FNode;
  358. // Init
  359. TNetData.NetData.OnReceivedHelloMessage := OnReceivedHelloMessage;
  360. TNetData.NetData.OnStatisticsChanged := OnNetStatisticsChanged;
  361. TNetData.NetData.OnNetConnectionsUpdated := onNetConnectionsUpdated;
  362. TNetData.NetData.OnNodeServersUpdated := OnNetNodeServersUpdated;
  363. TNetData.NetData.OnBlackListUpdated := OnNetBlackListUpdated;
  364. //
  365. TimerUpdateStatus.Interval := 1000;
  366. TimerUpdateStatus.Enabled := true;
  367. UpdateConfigChanged;
  368. Except
  369. On E:Exception do begin
  370. E.Message := 'An error occurred during initialization. Application cannot continue:'+#10+#10+E.Message+#10+#10+'Application will close...';
  371. Application.MessageBox(PChar(E.Message),PChar(Application.Title),MB_ICONERROR+MB_OK);
  372. Halt;
  373. end;
  374. end;
  375. UpdatePrivateKeys;
  376. UpdateAccounts(false);
  377. if FAppParams.ParamByName[CT_PARAM_FirstTime].GetAsBoolean(true) then begin
  378. FAppParams.ParamByName[CT_PARAM_FirstTime].SetAsBoolean(false);
  379. miAboutPascalCoinClick(Nil);
  380. end;
  381. end;
  382. procedure TFRMWallet.ApplicationEventsMinimize(Sender: TObject);
  383. begin
  384. {$IFnDEF FPC}
  385. Hide();
  386. WindowState := wsMinimized;
  387. TimerUpdateStatus.Enabled := false;
  388. { Show the animated tray icon and also a hint balloon. }
  389. TrayIcon.Visible := True;
  390. TrayIcon.ShowBalloonHint;
  391. {$ENDIF}
  392. end;
  393. procedure TFRMWallet.bbAccountsRefreshClick(Sender: TObject);
  394. begin
  395. UpdateAccounts(true);
  396. end;
  397. procedure TFRMWallet.bbChangeKeyNameClick(Sender: TObject);
  398. var i : Integer;
  399. name : String;
  400. begin
  401. if (cbMyPrivateKeys.ItemIndex<0) then exit;
  402. i := PtrInt(cbMyPrivateKeys.Items.Objects[cbMyPrivateKeys.ItemIndex]);
  403. if (i<0) Or (i>=FWalletKeys.Count) then raise Exception.Create('Must select a Key');
  404. name := FWalletKeys.Key[i].Name;
  405. if InputQuery('Change Key name','Input new name',name) then begin
  406. FWalletKeys.SetName(i,name);
  407. end;
  408. UpdatePrivateKeys;
  409. end;
  410. procedure TFRMWallet.bbSelectedAccountsOperationClick(Sender: TObject);
  411. var l : TOrderedCardinalList;
  412. begin
  413. CheckIsReady;
  414. if FSelectedAccountsGrid.AccountsCount<=0 then raise Exception.Create('Must select at least 1 account');
  415. With TFRMOperation.Create(Self) do
  416. Try
  417. l := FSelectedAccountsGrid.LockAccountsList;
  418. try
  419. SenderAccounts.CopyFrom(l);
  420. finally
  421. FSelectedAccountsGrid.UnlockAccountsList;
  422. end;
  423. DefaultFee := FAppParams.ParamByName[CT_PARAM_DefaultFee].GetAsInt64(0);
  424. WalletKeys := FWalletKeys;
  425. ShowModal;
  426. Finally
  427. Free;
  428. End;
  429. end;
  430. procedure TFRMWallet.bbSendAMessageClick(Sender: TObject);
  431. Var basem,m : String;
  432. them, errors : AnsiString;
  433. i,n : Integer;
  434. nc : TNetConnection;
  435. begin
  436. CheckIsReady;
  437. if (lbNetConnections.SelCount<=0) Or (lbNetConnections.ItemIndex<0) then raise Exception.Create('Select at least one connection');
  438. if lbNetConnections.SelCount<=0 then n := 1
  439. else n := lbNetConnections.SelCount;
  440. basem := memoMessageToSend.Lines.Text;
  441. m := '';
  442. // Clear non valid characters:
  443. for i := 1 to length(basem) do begin
  444. if basem[i] in [#32..#127] then m := m + basem[i]
  445. else m:=m+'.';
  446. end;
  447. if trim(m)='' then raise Exception.Create('No message');
  448. if Application.MessageBox(PChaR('Send this message to '+inttostr(n)+' nodes?'+#10+
  449. 'NOTE: Sending unauthorized messages will be considered spam and you will be banned'+#10+
  450. #10+
  451. 'Message: '+#10+
  452. m),PChar(Application.Title),MB_ICONQUESTION+MB_YESNO+MB_DEFBUTTON1)<>IdYes then exit;
  453. them := m;
  454. if n>1 then begin
  455. for i := 0 to lbNetConnections.Items.Count - 1 do begin
  456. if lbNetConnections.Selected[i] then begin
  457. nc := TNetConnection(lbNetconnections.Items.Objects[i]);
  458. if TNetData.NetData.ConnectionExistsAndActive(nc) then begin
  459. FNode.SendNodeMessage(nc,m,errors);
  460. memoMessages.Lines.Add(DateTimeToStr(now)+' Sent to '+nc.ClientRemoteAddr+' > '+m);
  461. end;
  462. end;
  463. end;
  464. end else begin
  465. nc := TNetConnection(lbNetconnections.Items.Objects[lbNetconnections.ItemIndex]);
  466. if TNetData.NetData.ConnectionExistsAndActive(nc) then begin
  467. FNode.SendNodeMessage(nc,m,errors);
  468. memoMessages.Lines.Add(DateTimeToStr(now)+' Sent to '+nc.ClientRemoteAddr+' > '+m);
  469. end;
  470. end;
  471. Application.MessageBox(PChaR('Message sent to '+inttostr(n)+' nodes'+#10+
  472. 'Message: '+#10+m),PChar(Application.Title),MB_ICONINFORMATION+MB_OK);
  473. end;
  474. procedure TFRMWallet.cbExploreMyAccountsClick(Sender: TObject);
  475. begin
  476. cbMyPrivateKeys.Enabled := cbExploreMyAccounts.Checked;
  477. UpdateAccounts(true);
  478. UpdateOperations;
  479. end;
  480. procedure TFRMWallet.cbFilterAccountsClick(Sender: TObject);
  481. begin
  482. If not DoUpdateAccountsFilter then UpdateAccounts(true);
  483. end;
  484. procedure TFRMWallet.cbMyPrivateKeysChange(Sender: TObject);
  485. begin
  486. UpdateAccounts(true);
  487. end;
  488. procedure TFRMWallet.CheckIsReady;
  489. Var isready : AnsiString;
  490. begin
  491. if Not Assigned(FNode) then Abort;
  492. if Not FNode.IsReady(isready) then begin
  493. Raise Exception.Create('You cannot do this operation now:'+#10+#10+isready);
  494. end;
  495. end;
  496. procedure TFRMWallet.CM_NetConnectionUpdated(var Msg: TMessage);
  497. Const CT_BooleanToString : Array[Boolean] of String = ('False','True');
  498. Var i : integer;
  499. NC : TNetConnection;
  500. l : TList;
  501. sClientApp, sLastConnTime : String;
  502. strings, sNSC, sRS, sDisc : TStrings;
  503. hh,nn,ss,ms : Word;
  504. begin
  505. Try
  506. if Not TNetData.NetData.NetConnections.TryLockList(100,l) then exit;
  507. try
  508. strings := memoNetConnections.Lines;
  509. sNSC := TStringList.Create;
  510. sRS := TStringList.Create;
  511. sDisc := TStringList.Create;
  512. strings.BeginUpdate;
  513. Try
  514. for i := 0 to l.Count - 1 do begin
  515. NC := l[i];
  516. If NC.Client.BytesReceived>0 then begin
  517. sClientApp := '['+IntToStr(NC.NetProtocolVersion.protocol_version)+'-'+IntToStr(NC.NetProtocolVersion.protocol_available)+'] '+NC.ClientAppVersion;
  518. end else begin
  519. sClientApp := '(no data)';
  520. end;
  521. if NC.Connected then begin
  522. if NC.Client.LastCommunicationTime>1000 then begin
  523. DecodeTime(now - NC.Client.LastCommunicationTime,hh,nn,ss,ms);
  524. if (hh=0) and (nn=0) And (ss<10) then begin
  525. sLastConnTime := ' - Last comunication <10 sec.';
  526. end else begin
  527. sLastConnTime := Format(' - Last comunication %.2dm%.2ds',[(hh*60)+nn,ss]);
  528. end;
  529. end else begin
  530. sLastConnTime := '';
  531. end;
  532. if NC is TNetServerClient then begin
  533. sNSC.Add(Format('Client: IP:%s Block:%d Sent/Received:%d/%d Bytes - %s - Time offset %d - Active since %s %s',
  534. [NC.ClientRemoteAddr,NC.RemoteOperationBlock.block,NC.Client.BytesSent,NC.Client.BytesReceived,sClientApp,NC.TimestampDiff,DateTimeElapsedTime(NC.CreatedTime),sLastConnTime]));
  535. end else begin
  536. if NC.IsMyselfServer then sNSC.Add(Format('MySelf IP:%s Sent/Received:%d/%d Bytes - %s - Time offset %d - Active since %s %s',
  537. [NC.ClientRemoteAddr,NC.Client.BytesSent,NC.Client.BytesReceived,sClientApp,NC.TimestampDiff,DateTimeElapsedTime(NC.CreatedTime),sLastConnTime]))
  538. else begin
  539. sRS.Add(Format('Remote Server: IP:%s Block:%d Sent/Received:%d/%d Bytes - %s - Time offset %d - Active since %s %s',
  540. [NC.ClientRemoteAddr,NC.RemoteOperationBlock.block,NC.Client.BytesSent,NC.Client.BytesReceived,sClientApp,NC.TimestampDiff,DateTimeElapsedTime(NC.CreatedTime),sLastConnTime]));
  541. end;
  542. end;
  543. end else begin
  544. if NC is TNetServerClient then begin
  545. sDisc.Add(Format('Disconnected client: IP:%s - %s',[NC.ClientRemoteAddr,sClientApp]));
  546. end else if NC.IsMyselfServer then begin
  547. sDisc.Add(Format('Disconnected MySelf IP:%s - %s',[NC.ClientRemoteAddr,sClientApp]));
  548. end else begin
  549. sDisc.Add(Format('Disconnected Remote Server: IP:%s %s - %s',[NC.ClientRemoteAddr,CT_BooleanToString[NC.Connected],sClientApp]));
  550. end;
  551. end;
  552. end;
  553. strings.Clear;
  554. strings.Add(Format('Connections Updated %s Clients:%d Servers:%d (valid servers:%d)',[DateTimeToStr(now),sNSC.Count,sRS.Count,TNetData.NetData.NetStatistics.ServersConnectionsWithResponse]));
  555. strings.AddStrings(sRS);
  556. strings.AddStrings(sNSC);
  557. if sDisc.Count>0 then begin
  558. strings.Add('');
  559. strings.Add('Disconnected connections: '+Inttostr(sDisc.Count));
  560. strings.AddStrings(sDisc);
  561. end;
  562. Finally
  563. strings.EndUpdate;
  564. sNSC.Free;
  565. sRS.Free;
  566. sDisc.Free;
  567. End;
  568. //CheckMining;
  569. finally
  570. TNetData.NetData.NetConnections.UnlockList;
  571. end;
  572. Finally
  573. FMustProcessNetConnectionUpdated := false;
  574. End;
  575. end;
  576. procedure TFRMWallet.CM_WalletChanged(var Msg: TMessage);
  577. begin
  578. UpdatePrivateKeys;
  579. FMustProcessWalletChanged := false;
  580. end;
  581. procedure TFRMWallet.dgAccountsClick(Sender: TObject);
  582. begin
  583. UpdateOperations;
  584. end;
  585. procedure TFRMWallet.dgAccountsColumnMoved(Sender: TObject; FromIndex, ToIndex: Integer);
  586. begin
  587. SaveAppParams;
  588. end;
  589. procedure TFRMWallet.dgAccountsFixedCellClick(Sender: TObject; ACol,
  590. ARow: Integer);
  591. begin
  592. SaveAppParams;
  593. end;
  594. procedure TFRMWallet.DoUpdateAccounts;
  595. begin
  596. UpdateAccounts(true);
  597. end;
  598. function TFRMWallet.DoUpdateAccountsFilter: Boolean;
  599. Var m,bmin,bmax:Int64;
  600. doupd : Boolean;
  601. begin
  602. if FUpdating then exit;
  603. FUpdating := true;
  604. Try
  605. If Not TAccountComp.TxtToMoney(ebFilterAccountByBalanceMin.Text,bmin) then bmin := 0;
  606. If not TAccountComp.TxtToMoney(ebFilterAccountByBalanceMax.Text,bmax) then bmax := CT_MaxWalletAmount;
  607. if (bmax<bmin) or (bmax=0) then bmax := CT_MaxWalletAmount;
  608. if bmin>bmax then bmin := 0;
  609. doupd := (bmin<>FMinAccountBalance) Or (bmax<>FMaxAccountBalance);
  610. FMinAccountBalance := bmin;
  611. FMaxAccountBalance := bmax;
  612. if bmin>0 then
  613. ebFilterAccountByBalanceMin.Text:=TAccountComp.FormatMoney(bmin)
  614. else ebFilterAccountByBalanceMin.Text := '';
  615. if bmax<CT_MaxWalletAmount then
  616. ebFilterAccountByBalanceMax.Text := TAccountComp.FormatMoney(bmax)
  617. else ebFilterAccountByBalanceMax.Text := '';
  618. if cbFilterAccounts.Checked then begin
  619. ebFilterAccountByBalanceMin.ParentFont := true;
  620. ebFilterAccountByBalanceMax.ParentFont := true;
  621. end else begin
  622. ebFilterAccountByBalanceMin.font.Color := clDkGray;
  623. ebFilterAccountByBalanceMax.font.Color := clDkGray;
  624. end;
  625. Finally
  626. FUpdating := false;
  627. End;
  628. if doupd then UpdateAccounts(true);
  629. Result := doupd;
  630. end;
  631. procedure TFRMWallet.ebBlockChainBlockStartExit(Sender: TObject);
  632. var bstart,bend : Int64;
  633. begin
  634. If FUpdating then exit;
  635. FUpdating := True;
  636. Try
  637. bstart := StrToInt64Def(ebBlockChainBlockStart.Text,-1);
  638. bend := StrToInt64Def(ebBlockChainBlockEnd.Text,-1);
  639. FBlockChainGrid.SetBlocks(bstart,bend);
  640. if FBlockChainGrid.BlockStart>=0 then ebBlockChainBlockStart.Text := Inttostr(FBlockChainGrid.BlockStart) else ebBlockChainBlockStart.Text := '';
  641. if FBlockChainGrid.BlockEnd>=0 then ebBlockChainBlockEnd.Text := Inttostr(FBlockChainGrid.BlockEnd) else ebBlockChainBlockEnd.Text := '';
  642. Finally
  643. FUpdating := false;
  644. End;
  645. end;
  646. procedure TFRMWallet.ebBlockChainBlockStartKeyPress(Sender: TObject;
  647. var Key: Char);
  648. begin
  649. if key=#13 then ebBlockChainBlockStartExit(Nil);
  650. end;
  651. procedure TFRMWallet.ebFilterAccountByBalanceMinExit(Sender: TObject);
  652. begin
  653. DoUpdateAccountsFilter;
  654. end;
  655. procedure TFRMWallet.ebFilterAccountByBalanceMinKeyPress(Sender: TObject;
  656. var Key: Char);
  657. begin
  658. if key=#13 then DoUpdateAccountsFilter;
  659. end;
  660. procedure TFRMWallet.ebFilterOperationsAccountExit(Sender: TObject);
  661. Var bstart,bend : Int64;
  662. begin
  663. If FUpdating then exit;
  664. FUpdating := True;
  665. Try
  666. bstart := StrToInt64Def(ebFilterOperationsStartBlock.Text,-1);
  667. if bstart>=0 then ebFilterOperationsStartBlock.Text := Inttostr(bstart) else ebFilterOperationsStartBlock.Text := '';
  668. bend := StrToInt64Def(ebFilterOperationsEndBlock.Text,-1);
  669. if bend>=0 then ebFilterOperationsEndBlock.Text := Inttostr(bend) else ebFilterOperationsEndBlock.Text := '';
  670. FOperationsExplorerGrid.SetBlocks(bstart,bend);
  671. Finally
  672. FUpdating := false;
  673. End;
  674. end;
  675. procedure TFRMWallet.ebFilterOperationsAccountKeyPress(Sender: TObject;
  676. var Key: Char);
  677. begin
  678. if key=#13 then ebFilterOperationsAccountExit(Nil);
  679. end;
  680. procedure TFRMWallet.ebFindAccountNumberChange(Sender: TObject);
  681. Var an : Cardinal;
  682. begin
  683. if Trim(ebFindAccountNumber.Text)='' then begin
  684. ebFindAccountNumber.Color := clWindow;
  685. ebFindAccountNumber.Font.Color := clDkGray;
  686. end else if TAccountComp.AccountTxtNumberToAccountNumber(ebFindAccountNumber.Text,an) then begin
  687. ebFindAccountNumber.Color := clWindow;
  688. if FAccountsGrid.MoveRowToAccount(an) then begin
  689. ebFindAccountNumber.Font.Color := clWindowText;
  690. end else begin
  691. ebFindAccountNumber.Font.Color := clRed;
  692. end;
  693. end else begin
  694. // Invalid value
  695. ebFindAccountNumber.Color := clRed;
  696. ebFindAccountNumber.Font.Color := clWindowText;
  697. end;
  698. end;
  699. procedure TFRMWallet.ebFindAccountNumberExit(Sender: TObject);
  700. begin
  701. ebFindAccountNumber.Text := '';
  702. end;
  703. procedure TFRMWallet.FinishedLoadingApp;
  704. begin
  705. FPoolMiningServer := TPoolMiningServer.Create;
  706. FPoolMiningServer.Port := FAppParams.ParamByName[CT_PARAM_JSONRPCMinerServerPort].GetAsInteger(CT_JSONRPCMinerServer_Port);
  707. FPoolMiningServer.MinerAccountKey := GetAccountKeyForMiner;
  708. FPoolMiningServer.MinerPayload := FAppParams.ParamByName[CT_PARAM_MinerName].GetAsString('');
  709. FNode.Operations.AccountKey := GetAccountKeyForMiner;
  710. FPoolMiningServer.Active := FAppParams.ParamByName[CT_PARAM_JSONRPCMinerServerActive].GetAsBoolean(true);
  711. FPoolMiningServer.OnMiningServerNewBlockFound := OnMiningServerNewBlockFound;
  712. If Assigned(FBackgroundPanel) then begin
  713. FreeAndNil(FBackgroundPanel);
  714. end;
  715. PageControl.Visible:=True;
  716. PageControl.Enabled:=True;
  717. end;
  718. procedure TFRMWallet.FillAccountInformation(const Strings: TStrings; Const AccountNumber: Cardinal);
  719. Var account : TAccount;
  720. s : String;
  721. begin
  722. if AccountNumber<0 then exit;
  723. account := FNode.Operations.SafeBoxTransaction.Account(AccountNumber);
  724. if account.name<>'' then s:='Name: '+account.name
  725. else s:='';
  726. Strings.Add(Format('Account: %s %s Type:%d',[TAccountComp.AccountNumberToAccountTxtNumber(AccountNumber),s,account.account_type]));
  727. Strings.Add('');
  728. Strings.Add(Format('Current balance: %s',[TAccountComp.FormatMoney(account.balance)]));
  729. Strings.Add('');
  730. Strings.Add(Format('Updated on block: %d (%d blocks ago)',[account.updated_block,FNode.Bank.BlocksCount-account.updated_block]));
  731. Strings.Add(Format('Public key type: %s',[TAccountComp.GetECInfoTxt(account.accountInfo.accountKey.EC_OpenSSL_NID)]));
  732. Strings.Add(Format('Base58 Public key: %s',[TAccountComp.AccountPublicKeyExport(account.accountInfo.accountKey)]));
  733. if TAccountComp.IsAccountForSale(account.accountInfo) then begin
  734. Strings.Add('');
  735. Strings.Add('** Account is for sale: **');
  736. Strings.Add(Format('Price: %s',[TAccountComp.FormatMoney(account.accountInfo.price)]));
  737. Strings.Add(Format('Seller account (where to pay): %s',[TAccountComp.AccountNumberToAccountTxtNumber(account.accountInfo.account_to_pay)]));
  738. if TAccountComp.IsAccountForSaleAcceptingTransactions(account.accountInfo) then begin
  739. Strings.Add('');
  740. Strings.Add('** Private sale **');
  741. Strings.Add(Format('New Base58 Public key: %s',[TAccountComp.AccountPublicKeyExport(account.accountInfo.new_publicKey)]));
  742. Strings.Add('');
  743. if TAccountComp.IsAccountLocked(account.accountInfo,FNode.Bank.BlocksCount) then begin
  744. Strings.Add(Format('PURCHASE IS SECURE UNTIL BLOCK %d (current %d, remains %d)',
  745. [account.accountInfo.locked_until_block,FNode.Bank.BlocksCount,account.accountInfo.locked_until_block-FNode.Bank.BlocksCount]));
  746. end else begin
  747. Strings.Add(Format('PURCHASE IS NOT SECURE (Expired on block %d, current %d)',
  748. [account.accountInfo.locked_until_block,FNode.Bank.BlocksCount]));
  749. end;
  750. end;
  751. end;
  752. end;
  753. procedure TFRMWallet.FillOperationInformation(const Strings: TStrings; Const OperationResume: TOperationResume);
  754. var i : Integer;
  755. jsonObj : TPCJSONObject;
  756. begin
  757. If (not OperationResume.valid) then exit;
  758. If OperationResume.Block<FNode.Bank.BlocksCount then
  759. if (OperationResume.NOpInsideBlock>=0) then begin
  760. Strings.Add(Format('Block: %d/%d',[OperationResume.Block,OperationResume.NOpInsideBlock]))
  761. end else begin
  762. Strings.Add(Format('Block: %d',[OperationResume.Block]))
  763. end
  764. else Strings.Add('** Pending operation not included on blockchain **');
  765. Strings.Add(Format('%s',[OperationResume.OperationTxt]));
  766. If (OperationResume.isMultiOperation) then begin
  767. Strings.Add('Multioperation:');
  768. For i := 0 to High(OperationResume.Senders) do begin
  769. Strings.Add(Format(' Sender (%d/%d): %s %s PASC Payload:%s',[i+1,length(OperationResume.Senders),TAccountComp.AccountNumberToAccountTxtNumber(OperationResume.Senders[i].Account),TAccountComp.FormatMoney(OperationResume.Senders[i].Amount),TCrypto.ToHexaString(OperationResume.Senders[i].Payload)]));
  770. end;
  771. For i := 0 to High(OperationResume.Receivers) do begin
  772. Strings.Add(Format(' Receiver (%d/%d): %s %s PASC Payload:%s',[i+1,length(OperationResume.Receivers),TAccountComp.AccountNumberToAccountTxtNumber(OperationResume.Receivers[i].Account),TAccountComp.FormatMoney(OperationResume.Receivers[i].Amount),TCrypto.ToHexaString(OperationResume.Receivers[i].Payload)]));
  773. end;
  774. For i := 0 to High(OperationResume.Changers) do begin
  775. Strings.Add(Format(' Change info (%d/%d): %s [%s]',[i+1,length(OperationResume.Changers),TAccountComp.AccountNumberToAccountTxtNumber(OperationResume.Changers[i].Account),TOpMultiOperation.OpChangeAccountInfoTypesToText(OperationResume.Changers[i].Changes_type)]));
  776. end;
  777. end;
  778. Strings.Add(Format('OpType:%d Subtype:%d',[OperationResume.OpType,OperationResume.OpSubtype]));
  779. Strings.Add(Format('Operation Hash (ophash): %s',[TCrypto.ToHexaString(OperationResume.OperationHash)]));
  780. If (OperationResume.OperationHash_OLD<>'') then begin
  781. Strings.Add(Format('Old Operation Hash (old_ophash): %s',[TCrypto.ToHexaString(OperationResume.OperationHash_OLD)]));
  782. end;
  783. if (OperationResume.OriginalPayload<>'') then begin
  784. Strings.Add(Format('Payload length:%d',[length(OperationResume.OriginalPayload)]));
  785. If OperationResume.PrintablePayload<>'' then begin
  786. Strings.Add(Format('Payload (human): %s',[OperationResume.PrintablePayload]));
  787. end;
  788. Strings.Add(Format('Payload (Hexadecimal): %s',[TCrypto.ToHexaString(OperationResume.OriginalPayload)]));
  789. end;
  790. If OperationResume.Balance>=0 then begin
  791. Strings.Add(Format('Final balance: %s',[TAccountComp.FormatMoney(OperationResume.Balance)]));
  792. end;
  793. jsonObj := TPCJSONObject.Create;
  794. Try
  795. TPascalCoinJSONComp.FillOperationObject(OperationResume,FNode.Bank.BlocksCount,jsonObj);
  796. Strings.Add('JSON:');
  797. Strings.Add(jsonObj.ToJSON(False));
  798. Finally
  799. jsonObj.Free;
  800. end;
  801. end;
  802. function TFRMWallet.ForceMining: Boolean;
  803. begin
  804. Result := false;
  805. end;
  806. procedure TFRMWallet.FormCreate(Sender: TObject);
  807. Var i : Integer;
  808. begin
  809. FLastNodesCacheUpdatedTS := Now;
  810. FBackgroundPanel := Nil;
  811. FMustProcessWalletChanged := false;
  812. FMustProcessNetConnectionUpdated := false;
  813. FRPCServer := Nil;
  814. FNode := Nil;
  815. FPoolMiningServer := Nil;
  816. FMinAccountBalance := 0;
  817. FMaxAccountBalance := CT_MaxWalletAmount;
  818. FMessagesUnreadCount := 0;
  819. lblReceivedMessages.Visible := false;
  820. memoNetConnections.Lines.Clear;
  821. memoNetServers.Lines.Clear;
  822. memoNetBlackLists.Lines.Clear;
  823. memoMessages.Lines.Clear;
  824. memoMessageToSend.Lines.Clear;
  825. FUpdating := false;
  826. FOrderedAccountsKeyList := Nil;
  827. TimerUpdateStatus.Enabled := false;
  828. FIsActivated := false;
  829. FWalletKeys := TWalletKeysExt.Create(Self);
  830. for i := 0 to StatusBar.Panels.Count - 1 do begin
  831. StatusBar.Panels[i].Text := '';
  832. end;
  833. FLog := TLog.Create(Self);
  834. FLog.OnNewLog := OnNewLog;
  835. FLog.SaveTypes := [];
  836. If Not ForceDirectories(TFolderHelper.GetPascalCoinDataFolder) then raise Exception.Create('Cannot create dir: '+TFolderHelper.GetPascalCoinDataFolder);
  837. FAppParams := TAppParams.Create(self);
  838. FAppParams.FileName := TFolderHelper.GetPascalCoinDataFolder+PathDelim+'AppParams.prm';
  839. FNodeNotifyEvents := TNodeNotifyEvents.Create(Self);
  840. FNodeNotifyEvents.OnBlocksChanged := OnNewAccount;
  841. FNodeNotifyEvents.OnNodeMessageEvent := OnNodeMessageEvent;
  842. FAccountsGrid := TAccountsGrid.Create(Self);
  843. FAccountsGrid.DrawGrid := dgAccounts;
  844. FAccountsGrid.AllowMultiSelect := True;
  845. FSelectedAccountsGrid := TAccountsGrid.Create(Self);
  846. FSelectedAccountsGrid.DrawGrid := dgSelectedAccounts;
  847. FSelectedAccountsGrid.OnUpdated := OnSelectedAccountsGridUpdated;
  848. FOperationsAccountGrid := TOperationsGrid.Create(Self);
  849. FOperationsAccountGrid.DrawGrid := dgAccountOperations;
  850. FOperationsAccountGrid.MustShowAlwaysAnAccount := true;
  851. FPendingOperationsGrid := TOperationsGrid.Create(Self);
  852. FPendingOperationsGrid.DrawGrid := dgPendingOperations;
  853. FPendingOperationsGrid.AccountNumber := -1; // all
  854. FPendingOperationsGrid.PendingOperations := true;
  855. FOperationsExplorerGrid := TOperationsGrid.Create(Self);
  856. FOperationsExplorerGrid.DrawGrid := dgOperationsExplorer;
  857. FOperationsExplorerGrid.AccountNumber := -1;
  858. FOperationsExplorerGrid.PendingOperations := False;
  859. FBlockChainGrid := TBlockChainGrid.Create(Self);
  860. FBlockChainGrid.DrawGrid := dgBlockChainExplorer;
  861. // FWalletKeys.OnChanged.Add( OnWalletChanged );
  862. LoadAppParams;
  863. UpdatePrivateKeys;
  864. UpdateBlockChainState;
  865. UpdateConnectionStatus;
  866. PageControl.ActivePage := tsMyAccounts;
  867. pcAccountsOptions.ActivePage := tsAccountOperations;
  868. ebFilterOperationsStartBlock.Text := '';
  869. ebFilterOperationsEndBlock.Text := '';
  870. cbExploreMyAccountsClick(nil);
  871. TrayIcon.Visible := true;
  872. TrayIcon.Hint := Self.Caption;
  873. TrayIcon.BalloonTitle := 'Restoring the window.';
  874. TrayIcon.BalloonHint :=
  875. 'Double click the system tray icon to restore Pascal Coin';
  876. TrayIcon.BalloonFlags := bfInfo;
  877. MinersBlocksFound := 0;
  878. lblBuild.Caption := 'Build: '+CT_ClientAppVersion;
  879. {$IFDEF TESTNET}
  880. Image1.visible := false;
  881. {$ENDIF}
  882. PageControl.Enabled := False;
  883. PageControl.Visible := False;
  884. FBackgroundPanel := TPanel.Create(Self);
  885. FBackgroundPanel.Parent:=Self;
  886. FBackgroundPanel.Align:=alClient;
  887. FBackgroundPanel.Font.Size:=15;
  888. end;
  889. procedure TFRMWallet.ebHashRateBackBlocksKeyPress(Sender: TObject; var Key: char);
  890. begin
  891. if Key=#13 then ebHashRateBackBlocksExit(Nil);
  892. end;
  893. procedure TFRMWallet.ebHashRateBackBlocksExit(Sender: TObject);
  894. var i : Integer;
  895. begin
  896. If FUpdating then exit;
  897. FUpdating := True;
  898. Try
  899. i := StrToIntDef(ebHashRateBackBlocks.Text,-1);
  900. FBlockChainGrid.HashRateAverageBlocksCount:=i;
  901. Finally
  902. ebHashRateBackBlocks.Text := IntToStr(FBlockChainGrid.HashRateAverageBlocksCount);
  903. FUpdating := false;
  904. End;
  905. end;
  906. procedure TFRMWallet.cbHashRateUnitsClick(Sender: TObject);
  907. begin
  908. If FUpdating then Exit;
  909. FUpdating := True;
  910. Try
  911. case cbHashRateUnits.ItemIndex of
  912. 0 : FBlockChainGrid.HashRateAs := hr_Kilo;
  913. 1 : FBlockChainGrid.HashRateAs := hr_Mega;
  914. 2 : FBlockChainGrid.HashRateAs := hr_Giga;
  915. 3 : FBlockChainGrid.HashRateAs := hr_Tera;
  916. else FBlockChainGrid.HashRateAs := hr_Mega;
  917. end;
  918. Finally
  919. FUpdating := false;
  920. End;
  921. end;
  922. procedure TFRMWallet.FormDestroy(Sender: TObject);
  923. Var i : Integer;
  924. step : String;
  925. begin
  926. TLog.NewLog(ltinfo,Classname,'Destroying form - START');
  927. Try
  928. FreeAndNil(FRPCServer);
  929. FreeAndNil(FPoolMiningServer);
  930. step := 'Saving params';
  931. SaveAppParams;
  932. FreeAndNil(FAppParams);
  933. //
  934. step := 'Assigning nil events';
  935. FLog.OnNewLog :=Nil;
  936. FNodeNotifyEvents.Node := Nil;
  937. FOperationsAccountGrid.Node := Nil;
  938. FOperationsExplorerGrid.Node := Nil;
  939. FPendingOperationsGrid.Node := Nil;
  940. FAccountsGrid.Node := Nil;
  941. FSelectedAccountsGrid.Node := Nil;
  942. TNetData.NetData.OnReceivedHelloMessage := Nil;
  943. TNetData.NetData.OnStatisticsChanged := Nil;
  944. TNetData.NetData.OnNetConnectionsUpdated := Nil;
  945. TNetData.NetData.OnNodeServersUpdated := Nil;
  946. TNetData.NetData.OnBlackListUpdated := Nil;
  947. //
  948. step := 'Destroying NodeNotifyEvents';
  949. FreeAndNil(FNodeNotifyEvents);
  950. //
  951. step := 'Assigning Nil to TNetData';
  952. TNetData.NetData.OnReceivedHelloMessage := Nil;
  953. TNetData.NetData.OnStatisticsChanged := Nil;
  954. step := 'Destroying grids operators';
  955. FreeAndNil(FOperationsAccountGrid);
  956. FreeAndNil(FOperationsExplorerGrid);
  957. FreeAndNil(FBlockChainGrid);
  958. step := 'Ordered Accounts Key list';
  959. FreeAndNil(FOrderedAccountsKeyList);
  960. step := 'Desactivating Node';
  961. TNode.Node.NetServer.Active := false;
  962. FNode := Nil;
  963. TNetData.NetData.Free;
  964. step := 'Processing messages 1';
  965. Application.ProcessMessages;
  966. step := 'Destroying Node';
  967. TNode.Node.Free;
  968. step := 'Destroying Wallet';
  969. FreeAndNil(FWalletKeys);
  970. step := 'Processing messages 2';
  971. Application.ProcessMessages;
  972. step := 'Destroying stringslist';
  973. Except
  974. On E:Exception do begin
  975. TLog.NewLog(lterror,Classname,'Error destroying Form step: '+step+' Errors ('+E.ClassName+'): ' +E.Message);
  976. end;
  977. End;
  978. TLog.NewLog(ltinfo,Classname,'Destroying form - END');
  979. FreeAndNil(FLog);
  980. Sleep(100);
  981. end;
  982. procedure TFRMWallet.MiOperationsExplorerClick(Sender: TObject);
  983. begin
  984. With TFRMOperationsExplorer.Create(Self) do
  985. try
  986. SourceNode := FNode;
  987. SourceWalletKeys := FWalletKeys;
  988. ShowModal;
  989. finally
  990. Free;
  991. end;
  992. end;
  993. procedure TFRMWallet.MiRPCCallsClick(Sender: TObject);
  994. Var FRM : TFRMRPCCalls;
  995. begin
  996. FRM := TFRMRPCCalls.Create(Self);
  997. Try
  998. FRM.ServerURL:='127.0.0.1:'+IntToStr(FRPCServer.Port);
  999. FRM.ShowModal;
  1000. finally
  1001. FRM.Free;
  1002. end;
  1003. end;
  1004. procedure TFRMWallet.sbSearchAccountClick(Sender: TObject);
  1005. Var F : TFRMAccountSelect;
  1006. begin
  1007. F := TFRMAccountSelect.Create(Self);
  1008. try
  1009. F.Node := FNode;
  1010. F.WalletKeys := FWalletKeys;
  1011. F.ShowModal;
  1012. finally
  1013. F.Free;
  1014. end;
  1015. end;
  1016. function TFRMWallet.GetAccountKeyForMiner: TAccountKey;
  1017. Var PK : TECPrivateKey;
  1018. i : Integer;
  1019. PublicK : TECDSA_Public;
  1020. begin
  1021. Result := CT_TECDSA_Public_Nul;
  1022. if Not Assigned(FWalletKeys) then exit;
  1023. if Not Assigned(FAppParams) then exit;
  1024. case FMinerPrivateKeyType of
  1025. mpk_NewEachTime: PublicK := CT_TECDSA_Public_Nul;
  1026. mpk_Selected: begin
  1027. PublicK := TAccountComp.RawString2Accountkey(FAppParams.ParamByName[CT_PARAM_MinerPrivateKeySelectedPublicKey].GetAsString(''));
  1028. end;
  1029. else
  1030. // Random
  1031. PublicK := CT_TECDSA_Public_Nul;
  1032. if FWalletKeys.Count>0 then PublicK := FWalletKeys.Key[Random(FWalletKeys.Count)].AccountKey;
  1033. end;
  1034. i := FWalletKeys.IndexOfAccountKey(PublicK);
  1035. if i>=0 then begin
  1036. if (FWalletKeys.Key[i].CryptedKey='') then i:=-1;
  1037. end;
  1038. if i<0 then begin
  1039. PK := TECPrivateKey.Create;
  1040. try
  1041. PK.GenerateRandomPrivateKey(CT_Default_EC_OpenSSL_NID);
  1042. FWalletKeys.AddPrivateKey('New for miner '+DateTimeToStr(Now), PK);
  1043. PublicK := PK.PublicKey;
  1044. finally
  1045. PK.Free;
  1046. end;
  1047. end;
  1048. Result := PublicK;
  1049. end;
  1050. procedure TFRMWallet.IPnodes1Click(Sender: TObject);
  1051. Var FRM : TFRMNodesIp;
  1052. begin
  1053. FRM := TFRMNodesIp.Create(Self);
  1054. Try
  1055. FRM.AppParams := FAppParams;
  1056. FRM.ShowModal;
  1057. Finally
  1058. FRM.Free;
  1059. End;
  1060. end;
  1061. procedure TFRMWallet.lblReceivedMessagesClick(Sender: TObject);
  1062. begin
  1063. PageControl.ActivePage := tsMessages;
  1064. end;
  1065. procedure TFRMWallet.LoadAppParams;
  1066. Var ms : TMemoryStream;
  1067. s : AnsiString;
  1068. fvi : TFileVersionInfo;
  1069. begin
  1070. ms := TMemoryStream.Create;
  1071. Try
  1072. s := FAppParams.ParamByName[CT_PARAM_GridAccountsStream].GetAsString('');
  1073. ms.WriteBuffer(s[1],length(s));
  1074. ms.Position := 0;
  1075. // Disabled on V2: FAccountsGrid.LoadFromStream(ms);
  1076. Finally
  1077. ms.Free;
  1078. End;
  1079. If FAppParams.FindParam(CT_PARAM_MinerName)=Nil then begin
  1080. // New configuration... assigning a new random value
  1081. fvi := TFolderHelper.GetTFileVersionInfo(Application.ExeName);
  1082. FAppParams.ParamByName[CT_PARAM_MinerName].SetAsString('New Node '+DateTimeToStr(Now)+' - '+
  1083. fvi.InternalName+' Build:'+fvi.FileVersion);
  1084. end;
  1085. FBlockChainGrid.ShowTimeAverageColumns:={$IFDEF SHOW_AVERAGE_TIME_STATS}True;{$ELSE}False;{$ENDIF}
  1086. UpdateConfigChanged;
  1087. end;
  1088. procedure TFRMWallet.miAboutPascalCoinClick(Sender: TObject);
  1089. begin
  1090. With TFRMAbout.Create(Self) do
  1091. try
  1092. showmodal;
  1093. finally
  1094. free;
  1095. end;
  1096. end;
  1097. procedure TFRMWallet.MiAccountInformationClick(Sender: TObject);
  1098. Var F : TFRMMemoText;
  1099. accn : Int64;
  1100. s,title : String;
  1101. account : TAccount;
  1102. strings : TStrings;
  1103. i : Integer;
  1104. opr : TOperationResume;
  1105. begin
  1106. accn := -1;
  1107. title := '';
  1108. strings := TStringList.Create;
  1109. try
  1110. opr := CT_TOperationResume_NUL;
  1111. if PageControl.ActivePage=tsOperations then begin
  1112. i := FOperationsExplorerGrid.DrawGrid.Row;
  1113. if (i>0) and (i<=FOperationsExplorerGrid.OperationsResume.Count) then begin
  1114. opr := FOperationsExplorerGrid.OperationsResume.OperationResume[i-1];
  1115. end;
  1116. end else if PageControl.ActivePage=tsPendingOperations then begin
  1117. i := FPendingOperationsGrid.DrawGrid.Row;
  1118. if (i>0) and (i<=FPendingOperationsGrid.OperationsResume.Count) then begin
  1119. opr := FPendingOperationsGrid.OperationsResume.OperationResume[i-1];
  1120. end;
  1121. end else if PageControl.ActivePage=tsMyAccounts then begin
  1122. accn := FAccountsGrid.AccountNumber(dgAccounts.Row);
  1123. if accn<0 then raise Exception.Create('Select an account');
  1124. FillAccountInformation(strings,accn);
  1125. title := 'Account '+TAccountComp.AccountNumberToAccountTxtNumber(accn)+' info';
  1126. i := FOperationsAccountGrid.DrawGrid.Row;
  1127. if (i>0) and (i<=FOperationsAccountGrid.OperationsResume.Count) then begin
  1128. opr := FOperationsAccountGrid.OperationsResume.OperationResume[i-1];
  1129. end;
  1130. end;
  1131. If (opr.valid) then begin
  1132. if accn>=0 then strings.Add('')
  1133. else title := 'Operation info';
  1134. strings.Add('Operation info:');
  1135. FillOperationInformation(strings,opr);
  1136. end else if accn<0 then Raise Exception.Create('No info available');
  1137. F := TFRMMemoText.Create(Self);
  1138. Try
  1139. F.Caption := title;
  1140. F.Memo.Lines.Assign(strings);
  1141. F.ShowModal;
  1142. Finally
  1143. F.Free;
  1144. End;
  1145. finally
  1146. strings.free;
  1147. end;
  1148. end;
  1149. procedure TFRMWallet.MiAddaccounttoSelectedClick(Sender: TObject);
  1150. begin
  1151. PageControl.ActivePage := tsMyAccounts;
  1152. PageControlChange(Nil);
  1153. pcAccountsOptions.ActivePage := tsMultiSelectAccounts;
  1154. sbSelectedAccountsAddClick(Sender);
  1155. end;
  1156. procedure TFRMWallet.MiCloseClick(Sender: TObject);
  1157. begin
  1158. Close;
  1159. end;
  1160. procedure TFRMWallet.MiDecodePayloadClick(Sender: TObject);
  1161. begin
  1162. if PageControl.ActivePage=tsOperations then begin
  1163. FOperationsExplorerGrid.ShowModalDecoder(FWalletKeys,FAppParams);
  1164. end else if PageControl.ActivePage=tsPendingOperations then begin
  1165. FPendingOperationsGrid.ShowModalDecoder(FWalletKeys,FAppParams);
  1166. end else if PageControl.ActivePage=tsMyAccounts then begin
  1167. FOperationsAccountGrid.ShowModalDecoder(FWalletKeys,FAppParams);
  1168. end;
  1169. end;
  1170. procedure TFRMWallet.MiFindaccountClick(Sender: TObject);
  1171. begin
  1172. PageControl.ActivePage := tsMyAccounts;
  1173. PageControlChange(Nil);
  1174. ebFindAccountNumber.SetFocus;
  1175. end;
  1176. procedure TFRMWallet.MiFindnextaccountwithhighbalanceClick(Sender: TObject);
  1177. Var an : Cardinal;
  1178. an64 : Int64;
  1179. start : TAccount;
  1180. begin
  1181. PageControl.ActivePage := tsMyAccounts;
  1182. PageControlChange(Nil);
  1183. an64 := FAccountsGrid.AccountNumber(dgAccounts.Row);
  1184. if an64<0 then an := 0
  1185. else an := an64;
  1186. If an>=FNode.Bank.SafeBox.AccountsCount then exit;
  1187. start := FNode.Bank.SafeBox.Account(an);
  1188. while (an<FNode.Bank.SafeBox.AccountsCount) do begin
  1189. if FNode.Bank.SafeBox.Account(an).balance>start.balance then break
  1190. else inc(an);
  1191. end;
  1192. if (an<FNode.Bank.SafeBox.AccountsCount) then FAccountsGrid.MoveRowToAccount(an)
  1193. else raise Exception.Create('Not found any account higher than '+TAccountComp.AccountNumberToAccountTxtNumber(start.account)+' with balance higher than '+
  1194. TAccountComp.FormatMoney(start.balance));
  1195. end;
  1196. procedure TFRMWallet.MiFindOperationbyOpHashClick(Sender: TObject);
  1197. Var FRM : TFRMPayloadDecoder;
  1198. oph : String;
  1199. begin
  1200. oph := '';
  1201. if Not InputQuery('Search operation by OpHash','Insert Operation Hash value (OpHash)',oph) then exit;
  1202. //
  1203. FRM := TFRMPayloadDecoder.Create(Self);
  1204. try
  1205. FRM.Init(CT_TOperationResume_NUL,WalletKeys,FAppParams);
  1206. FRM.DoFind(oph);
  1207. FRM.ShowModal;
  1208. finally
  1209. FRM.Free;
  1210. end;
  1211. end;
  1212. procedure TFRMWallet.MiFindpreviousaccountwithhighbalanceClick(Sender: TObject);
  1213. Var an : Cardinal;
  1214. an64 : Int64;
  1215. start : TAccount;
  1216. begin
  1217. PageControl.ActivePage := tsMyAccounts;
  1218. PageControlChange(Nil);
  1219. an64 := FAccountsGrid.AccountNumber(dgAccounts.Row);
  1220. if an64<0 then an := FNode.Bank.SafeBox.AccountsCount-1
  1221. else an := an64;
  1222. If an>=FNode.Bank.SafeBox.AccountsCount then exit;
  1223. start := FNode.Bank.SafeBox.Account(an);
  1224. while (an>0) do begin
  1225. if FNode.Bank.SafeBox.Account(an).balance>start.balance then break
  1226. else dec(an);
  1227. end;
  1228. if (FNode.Bank.SafeBox.Account(an).balance>start.balance) then FAccountsGrid.MoveRowToAccount(an)
  1229. else raise Exception.Create('Not found any account lower than '+TAccountComp.AccountNumberToAccountTxtNumber(start.account)+' with balance higher than '+
  1230. TAccountComp.FormatMoney(start.balance));
  1231. end;
  1232. procedure TFRMWallet.MiMultiaccountoperationClick(Sender: TObject);
  1233. begin
  1234. PageControl.ActivePage := tsMyAccounts;
  1235. pcAccountsOptions.ActivePage := tsMultiSelectAccounts;
  1236. bbSelectedAccountsOperationClick(Sender);
  1237. end;
  1238. procedure TFRMWallet.miNewOperationClick(Sender: TObject);
  1239. var l : TOrderedCardinalList;
  1240. begin
  1241. CheckIsReady;
  1242. With TFRMOperation.Create(Self) do
  1243. Try
  1244. l := TOrderedCardinalList.Create;
  1245. try
  1246. If FAccountsGrid.SelectedAccounts(l)<1 then raise Exception.Create('No row selected');
  1247. SenderAccounts.CopyFrom(l);
  1248. finally
  1249. l.Free;
  1250. end;
  1251. DefaultFee := FAppParams.ParamByName[CT_PARAM_DefaultFee].GetAsInt64(0);
  1252. WalletKeys := FWalletKeys;
  1253. ShowModal;
  1254. Finally
  1255. Free;
  1256. End;
  1257. end;
  1258. procedure TFRMWallet.miOptionsClick(Sender: TObject);
  1259. begin
  1260. With TFRMPascalCoinWalletConfig.Create(Self) do
  1261. try
  1262. AppParams := Self.FAppParams;
  1263. WalletKeys := Self.FWalletKeys;
  1264. if ShowModal=MrOk then begin
  1265. SaveAppParams;
  1266. UpdateConfigChanged;
  1267. end;
  1268. finally
  1269. free;
  1270. end;
  1271. end;
  1272. procedure TFRMWallet.miPrivatekeysClick(Sender: TObject);
  1273. Var FRM : TFRMWalletKeys;
  1274. begin
  1275. FRM := TFRMWalletKeys.Create(Self);
  1276. Try
  1277. FRM.WalletKeys := FWalletKeys;
  1278. FRM.ShowModal;
  1279. UpdatePrivateKeys;
  1280. Finally
  1281. FRM.Free;
  1282. End;
  1283. end;
  1284. procedure TFRMWallet.MiRemoveaccountfromselectedClick(Sender: TObject);
  1285. begin
  1286. PageControl.ActivePage := tsMyAccounts;
  1287. PageControlChange(Nil);
  1288. pcAccountsOptions.ActivePage := tsMultiSelectAccounts;
  1289. sbSelectedAccountsDelClick(Sender);
  1290. end;
  1291. procedure TFRMWallet.OnMiningServerNewBlockFound(Sender: TObject);
  1292. begin
  1293. FPoolMiningServer.MinerAccountKey := GetAccountKeyForMiner;
  1294. end;
  1295. procedure TFRMWallet.OnNetBlackListUpdated(Sender: TObject);
  1296. Const CT_TRUE_FALSE : Array[Boolean] Of AnsiString = ('FALSE','TRUE');
  1297. Var i,j,n : integer;
  1298. P : PNodeServerAddress;
  1299. l : TList;
  1300. strings : TStrings;
  1301. begin
  1302. l := TNetData.NetData.NodeServersAddresses.LockList;
  1303. try
  1304. strings := memoNetBlackLists.Lines;
  1305. strings.BeginUpdate;
  1306. Try
  1307. strings.Clear;
  1308. strings.Add('BlackList Updated: '+DateTimeToStr(now)+' by TID:'+IntToHex(PtrInt(TThread.CurrentThread.ThreadID),8));
  1309. j := 0; n:=0;
  1310. for i := 0 to l.Count - 1 do begin
  1311. P := l[i];
  1312. if (P^.is_blacklisted) then begin
  1313. inc(n);
  1314. if Not P^.its_myself then begin
  1315. inc(j);
  1316. strings.Add(Format('Blacklist IP:%s:%d LastConnection:%s Reason: %s',
  1317. [
  1318. P^.ip,P^.port,
  1319. DateTimeToStr(UnivDateTime2LocalDateTime( UnixToUnivDateTime(P^.last_connection))),P^.BlackListText]));
  1320. end;
  1321. end;
  1322. end;
  1323. Strings.Add(Format('Total Blacklisted IPs: %d (Total %d)',[j,n]));
  1324. Finally
  1325. strings.EndUpdate;
  1326. End;
  1327. finally
  1328. TNetData.NetData.NodeServersAddresses.UnlockList;
  1329. end;
  1330. end;
  1331. procedure TFRMWallet.OnNetConnectionsUpdated(Sender: TObject);
  1332. begin
  1333. if FMustProcessNetConnectionUpdated then exit;
  1334. FMustProcessNetConnectionUpdated := true;
  1335. PostMessage(Self.Handle,CM_PC_NetConnectionUpdated,0,0);
  1336. end;
  1337. procedure TFRMWallet.OnNetNodeServersUpdated(Sender: TObject);
  1338. Var i : integer;
  1339. P : PNodeServerAddress;
  1340. l : TList;
  1341. strings : TStrings;
  1342. s : String;
  1343. begin
  1344. l := TNetData.NetData.NodeServersAddresses.LockList;
  1345. try
  1346. strings := memoNetServers.Lines;
  1347. strings.BeginUpdate;
  1348. Try
  1349. strings.Clear;
  1350. strings.Add('NodeServers Updated: '+DateTimeToStr(now) +' Count: '+inttostr(l.Count));
  1351. for i := 0 to l.Count - 1 do begin
  1352. P := l[i];
  1353. if Not (P^.is_blacklisted) then begin
  1354. s := Format('Server IP:%s:%d',[P^.ip,P^.port]);
  1355. if (P^.last_connection_by_me>0) then begin
  1356. s := s + ' [Server] ';
  1357. end;
  1358. if Assigned(P.netConnection) then begin
  1359. If P.last_connection>0 then s := s+ ' ** ACTIVE **'
  1360. else s := s+' ** TRYING TO CONNECT **';
  1361. end;
  1362. if P.its_myself then begin
  1363. s := s+' ** NOT VALID ** '+P.BlackListText;
  1364. end;
  1365. if P.last_connection>0 then begin
  1366. s := s + ' Last connection: '+DateTimeToStr(UnivDateTime2LocalDateTime( UnixToUnivDateTime(P^.last_connection)));
  1367. end;
  1368. if P.last_connection_by_server>0 then begin
  1369. s := s + ' Last server connection: '+DateTimeToStr(UnivDateTime2LocalDateTime( UnixToUnivDateTime(P^.last_connection_by_server)));
  1370. end;
  1371. if (P.last_attempt_to_connect>0) then begin
  1372. s := s + ' Last attempt to connect: '+DateTimeToStr(P^.last_attempt_to_connect);
  1373. end;
  1374. if (P.total_failed_attemps_to_connect>0) then begin
  1375. s := s + ' (Attempts: '+inttostr(P^.total_failed_attemps_to_connect)+')';
  1376. end;
  1377. strings.Add(s);
  1378. end;
  1379. end;
  1380. Finally
  1381. strings.EndUpdate;
  1382. End;
  1383. finally
  1384. TNetData.NetData.NodeServersAddresses.UnlockList;
  1385. end;
  1386. end;
  1387. procedure TFRMWallet.OnNetStatisticsChanged(Sender: TObject);
  1388. Var NS : TNetStatistics;
  1389. begin
  1390. //CheckMining;
  1391. if Assigned(FNode) then begin
  1392. If FNode.NetServer.Active then begin
  1393. StatusBar.Panels[0].Text := 'Active (Port '+Inttostr(FNode.NetServer.Port)+')';
  1394. end else StatusBar.Panels[0].Text := 'Server stopped';
  1395. NS := TNetData.NetData.NetStatistics;
  1396. StatusBar.Panels[1].Text := Format('Connections:%d Clients:%d Servers:%d - Rcvd:%d Kb Send:%d Kb',
  1397. [NS.ActiveConnections,NS.ClientsConnections,NS.ServersConnections,NS.BytesReceived DIV 1024,NS.BytesSend DIV 1024]);
  1398. end else begin
  1399. StatusBar.Panels[0].Text := '';
  1400. StatusBar.Panels[1].Text := '';
  1401. end;
  1402. end;
  1403. procedure TFRMWallet.OnNewAccount(Sender: TObject);
  1404. begin
  1405. Try
  1406. UpdateAccounts(false);
  1407. UpdateBlockChainState;
  1408. Except
  1409. On E:Exception do begin
  1410. E.Message := 'Error at OnNewAccount '+E.Message;
  1411. Raise;
  1412. end;
  1413. end;
  1414. end;
  1415. procedure TFRMWallet.OnNewLog(logtype: TLogType; Time : TDateTime; ThreadID : TThreadID; const sender,logtext: AnsiString);
  1416. Var s : AnsiString;
  1417. begin
  1418. if (logtype=ltdebug) And (Not cbShowDebugLogs.Checked) then exit;
  1419. if ThreadID=MainThreadID then s := ' MAIN:' else s:=' TID:';
  1420. if MemoLogs.Lines.Count>300 then begin
  1421. // Limit max lines in logs...
  1422. memoLogs.Lines.BeginUpdate;
  1423. try
  1424. while memoLogs.Lines.Count>250 do memoLogs.Lines.Delete(0);
  1425. finally
  1426. memoLogs.Lines.EndUpdate;
  1427. end;
  1428. end;
  1429. memoLogs.Lines.Add(formatDateTime('dd/mm/yyyy hh:nn:ss.zzz',Time)+s+IntToHex(PtrInt(ThreadID),8)+' ['+CT_LogType[Logtype]+'] <'+sender+'> '+logtext);
  1430. //
  1431. end;
  1432. procedure TFRMWallet.OnNodeMessageEvent(NetConnection: TNetConnection; MessageData: TRawBytes);
  1433. Var s : String;
  1434. begin
  1435. inc(FMessagesUnreadCount);
  1436. if Assigned(NetConnection) then begin
  1437. s := DateTimeToStr(now)+' Message received from '+NetConnection.ClientRemoteAddr;
  1438. memoMessages.Lines.Add(DateTimeToStr(now)+' Message received from '+NetConnection.ClientRemoteAddr+' Length '+inttostr(Length(MessageData))+' bytes');
  1439. memoMessages.Lines.Add('RECEIVED> '+MessageData);
  1440. if FAppParams.ParamByName[CT_PARAM_ShowModalMessages].GetAsBoolean(false) then begin
  1441. s := DateTimeToStr(now)+' Message from '+NetConnection.ClientRemoteAddr+#10+
  1442. 'Length '+inttostr(length(MessageData))+' bytes'+#10+#10;
  1443. if TCrypto.IsHumanReadable(MessageData) then begin
  1444. s := s + MessageData;
  1445. end else begin
  1446. s := s +'Value in hexadecimal:'+#10+
  1447. TCrypto.ToHexaString(MessageData);
  1448. end;
  1449. Application.MessageBox(PChar(s),PChar(Application.Title),MB_ICONINFORMATION+MB_OK);
  1450. end;
  1451. end else begin
  1452. memoMessages.Lines.Add(DateTimeToStr(now)+' Internal message: '+MessageData);
  1453. end;
  1454. if FMessagesUnreadCount>1 then lblReceivedMessages.Caption := Format('You have received %d messages',[FMessagesUnreadCount])
  1455. else lblReceivedMessages.Caption := 'You have received 1 message';
  1456. lblReceivedMessages.Visible := true;
  1457. end;
  1458. procedure TFRMWallet.OnReceivedHelloMessage(Sender: TObject);
  1459. Var nsarr : TNodeServerAddressArray;
  1460. i : Integer;
  1461. s : AnsiString;
  1462. begin
  1463. If (FLastNodesCacheUpdatedTS + EncodeTime(0,5,0,0) > Now) then exit; // Prevent continuous saving
  1464. FLastNodesCacheUpdatedTS := Now;
  1465. // Update node servers Peer Cache
  1466. nsarr := TNetData.NetData.NodeServersAddresses.GetValidNodeServers(true,0);
  1467. s := '';
  1468. for i := low(nsarr) to High(nsarr) do begin
  1469. if (s<>'') then s := s+';';
  1470. s := s + nsarr[i].ip+':'+IntToStr( nsarr[i].port );
  1471. end;
  1472. FAppParams.ParamByName[CT_PARAM_PeerCache].SetAsString(s);
  1473. TNode.Node.PeerCache := s;
  1474. end;
  1475. procedure TFRMWallet.OnSelectedAccountsGridUpdated(Sender: TObject);
  1476. begin
  1477. lblSelectedAccountsCount.Caption := Inttostr(FSelectedAccountsGrid.AccountsCount);
  1478. lblSelectedAccountsBalance.Caption := TAccountComp.FormatMoney( FSelectedAccountsGrid.AccountsBalance );
  1479. end;
  1480. procedure TFRMWallet.OnWalletChanged(Sender: TObject);
  1481. begin
  1482. if FMustProcessWalletChanged then exit;
  1483. FMustProcessWalletChanged := true;
  1484. PostMessage(Self.Handle,CM_PC_WalletKeysChanged,0,0);
  1485. end;
  1486. procedure TFRMWallet.PageControlChange(Sender: TObject);
  1487. begin
  1488. MiDecodePayload.Enabled := false;
  1489. if PageControl.ActivePage=tsMyAccounts then begin
  1490. //FAccountsGrid.Node := FNode;
  1491. MiDecodePayload.Enabled := true;
  1492. FSelectedAccountsGrid.Node := FNode;
  1493. end else begin
  1494. //FAccountsGrid.Node := Nil;
  1495. FSelectedAccountsGrid.Node := Nil;
  1496. end;
  1497. if PageControl.ActivePage=tsPendingOperations then begin
  1498. FPendingOperationsGrid.Node := FNode;
  1499. MiDecodePayload.Enabled := true;
  1500. end else FPendingOperationsGrid.Node := Nil;
  1501. if PageControl.ActivePage=tsBlockChain then FBlockChainGrid.Node := FNode
  1502. else FBlockChainGrid.Node := Nil;
  1503. if PageControl.ActivePage=tsOperations then begin
  1504. FOperationsExplorerGrid.Node := FNode;
  1505. MiDecodePayload.Enabled := true;
  1506. end else FOperationsExplorerGrid.Node := Nil;
  1507. if PageControl.ActivePage=tsMessages then begin
  1508. UpdateAvailableConnections;
  1509. FMessagesUnreadCount := 0;
  1510. lblReceivedMessages.Visible := false;
  1511. end;
  1512. end;
  1513. procedure TFRMWallet.SaveAppParams;
  1514. Var ms : TMemoryStream;
  1515. s : AnsiString;
  1516. begin
  1517. ms := TMemoryStream.Create;
  1518. Try
  1519. FAccountsGrid.SaveToStream(ms);
  1520. ms.Position := 0;
  1521. setlength(s,ms.Size);
  1522. ms.ReadBuffer(s[1],ms.Size);
  1523. FAppParams.ParamByName[CT_PARAM_GridAccountsStream].SetAsString(s);
  1524. Finally
  1525. ms.Free;
  1526. End;
  1527. end;
  1528. procedure TFRMWallet.sbSelectedAccountsAddAllClick(Sender: TObject);
  1529. Var lsource,ltarget : TOrderedCardinalList;
  1530. i : Integer;
  1531. begin
  1532. lsource := FAccountsGrid.LockAccountsList;
  1533. Try
  1534. ltarget := FSelectedAccountsGrid.LockAccountsList;
  1535. Try
  1536. for i := 0 to lsource.Count-1 do begin
  1537. if FWalletKeys.IndexOfAccountKey(FNode.Bank.SafeBox.Account(lsource.Get(i)).accountInfo.accountKey)<0 then raise Exception.Create(Format('You cannot operate with account %d because private key not found in your wallet',[lsource.Get(i)]));
  1538. ltarget.Add(lsource.Get(i));
  1539. end;
  1540. Finally
  1541. FSelectedAccountsGrid.UnlockAccountsList;
  1542. End;
  1543. Finally
  1544. FAccountsGrid.UnlockAccountsList;
  1545. End;
  1546. end;
  1547. procedure TFRMWallet.sbSelectedAccountsAddClick(Sender: TObject);
  1548. Var l, selected : TOrderedCardinalList;
  1549. an : Int64;
  1550. i : Integer;
  1551. begin
  1552. an := FAccountsGrid.AccountNumber(dgAccounts.Row);
  1553. if (an<0) then raise Exception.Create('No account selected');
  1554. if FWalletKeys.IndexOfAccountKey(FNode.Bank.SafeBox.Account(an).accountInfo.accountkey)<0 then
  1555. raise Exception.Create(Format('You cannot add %s account because private key not found in your wallet.'#10+#10+'You''re not the owner!',
  1556. [TAccountComp.AccountNumberToAccountTxtNumber(an)]));
  1557. // Add
  1558. l := FSelectedAccountsGrid.LockAccountsList;
  1559. selected := TOrderedCardinalList.Create;
  1560. Try
  1561. FAccountsGrid.SelectedAccounts(selected);
  1562. for i := 0 to selected.Count-1 do begin
  1563. l.Add(selected.Get(i));
  1564. end;
  1565. Finally
  1566. selected.Free;
  1567. FSelectedAccountsGrid.UnlockAccountsList;
  1568. End;
  1569. end;
  1570. procedure TFRMWallet.sbSelectedAccountsDelAllClick(Sender: TObject);
  1571. Var l : TOrderedCardinalList;
  1572. begin
  1573. l := FSelectedAccountsGrid.LockAccountsList;
  1574. try
  1575. l.Clear;
  1576. finally
  1577. FSelectedAccountsGrid.UnlockAccountsList;
  1578. end;
  1579. end;
  1580. procedure TFRMWallet.sbSelectedAccountsDelClick(Sender: TObject);
  1581. Var an : Int64;
  1582. l : TOrderedCardinalList;
  1583. begin
  1584. l := FSelectedAccountsGrid.LockAccountsList;
  1585. try
  1586. an := FSelectedAccountsGrid.AccountNumber(dgSelectedAccounts.Row);
  1587. if an>=0 then l.Remove(an);
  1588. finally
  1589. FSelectedAccountsGrid.UnlockAccountsList;
  1590. end;
  1591. end;
  1592. procedure TFRMWallet.SetMinersBlocksFound(const Value: Integer);
  1593. begin
  1594. FMinersBlocksFound := Value;
  1595. lblBlocksFound.Caption := Inttostr(Value);
  1596. if Value>0 then lblBlocksFound.Font.Color := clGreen
  1597. else lblBlocksFound.Font.Color := clDkGray;
  1598. end;
  1599. procedure TFRMWallet.TimerUpdateStatusTimer(Sender: TObject);
  1600. begin
  1601. Try
  1602. UpdateConnectionStatus;
  1603. UpdateBlockChainState;
  1604. UpdateNodeStatus;
  1605. Except
  1606. On E:Exception do begin
  1607. E.Message := 'Exception at TimerUpdate '+E.ClassName+': '+E.Message;
  1608. TLog.NewLog(lterror,ClassName,E.Message);
  1609. end;
  1610. End;
  1611. end;
  1612. procedure TFRMWallet.TrayIconDblClick(Sender: TObject);
  1613. begin
  1614. TrayIcon.Visible := False;
  1615. TimerUpdateStatus.Enabled := true;
  1616. Show();
  1617. WindowState := wsNormal;
  1618. Application.BringToFront();
  1619. end;
  1620. procedure TFRMWallet.UpdateAccounts(RefreshData : Boolean);
  1621. Var accl : TOrderedCardinalList;
  1622. l : TOrderedCardinalList;
  1623. i,j,k : Integer;
  1624. c : Cardinal;
  1625. applyfilter : Boolean;
  1626. acc : TAccount;
  1627. begin
  1628. If Not Assigned(FOrderedAccountsKeyList) Then exit;
  1629. if Not RefreshData then begin
  1630. dgAccounts.Invalidate;
  1631. exit;
  1632. end;
  1633. applyfilter := (cbFilterAccounts.Checked) and ((FMinAccountBalance>0) Or (FMaxAccountBalance<CT_MaxWalletAmount));
  1634. FAccountsGrid.ShowAllAccounts := (Not cbExploreMyAccounts.Checked) And (not applyfilter);
  1635. if Not FAccountsGrid.ShowAllAccounts then begin
  1636. accl := FAccountsGrid.LockAccountsList;
  1637. Try
  1638. accl.Clear;
  1639. if cbExploreMyAccounts.Checked then begin
  1640. if cbMyPrivateKeys.ItemIndex<0 then exit;
  1641. if cbMyPrivateKeys.ItemIndex=0 then begin
  1642. // All keys in the wallet
  1643. for i := 0 to FWalletKeys.Count - 1 do begin
  1644. j := FOrderedAccountsKeyList.IndexOfAccountKey(FWalletKeys[i].AccountKey);
  1645. if (j>=0) then begin
  1646. l := FOrderedAccountsKeyList.AccountKeyList[j];
  1647. for k := 0 to l.Count - 1 do begin
  1648. if applyfilter then begin
  1649. acc := FNode.Bank.SafeBox.Account(l.Get(k));
  1650. if (acc.balance>=FMinAccountBalance) And (acc.balance<=FMaxAccountBalance) then accl.Add(acc.account);
  1651. end else accl.Add(l.Get(k));
  1652. end;
  1653. end;
  1654. end;
  1655. end else begin
  1656. i := PtrInt(cbMyPrivateKeys.Items.Objects[cbMyPrivateKeys.ItemIndex]);
  1657. if (i>=0) And (i<FWalletKeys.Count) then begin
  1658. j := FOrderedAccountsKeyList.IndexOfAccountKey(FWalletKeys[i].AccountKey);
  1659. if (j>=0) then begin
  1660. l := FOrderedAccountsKeyList.AccountKeyList[j];
  1661. for k := 0 to l.Count - 1 do begin
  1662. if applyfilter then begin
  1663. acc := FNode.Bank.SafeBox.Account(l.Get(k));
  1664. if (acc.balance>=FMinAccountBalance) And (acc.balance<=FMaxAccountBalance) then accl.Add(acc.account);
  1665. end else accl.Add(l.Get(k));
  1666. end;
  1667. end;
  1668. end;
  1669. end;
  1670. end else begin
  1671. // There is a filter... check every account...
  1672. c := 0;
  1673. while (c<FNode.Bank.SafeBox.AccountsCount) do begin
  1674. acc := FNode.Bank.SafeBox.Account(c);
  1675. if (acc.balance>=FMinAccountBalance) And (acc.balance<=FMaxAccountBalance) then accl.Add(acc.account);
  1676. inc(c);
  1677. end;
  1678. end;
  1679. Finally
  1680. FAccountsGrid.UnlockAccountsList;
  1681. End;
  1682. lblAccountsCount.Caption := inttostr(accl.Count);
  1683. end else begin
  1684. lblAccountsCount.Caption := inttostr(FNode.Bank.AccountsCount);
  1685. end;
  1686. bbChangeKeyName.Enabled := cbExploreMyAccounts.Checked;
  1687. // Show Totals:
  1688. lblAccountsBalance.Caption := TAccountComp.FormatMoney(FAccountsGrid.AccountsBalance);
  1689. UpdateOperations;
  1690. end;
  1691. procedure TFRMWallet.UpdateAvailableConnections;
  1692. Var i : integer;
  1693. NC : TNetConnection;
  1694. l : TList;
  1695. begin
  1696. if Not TNetData.NetData.NetConnections.TryLockList(100,l) then exit;
  1697. try
  1698. lbNetConnections.Items.BeginUpdate;
  1699. Try
  1700. lbNetConnections.Items.Clear;
  1701. for i := 0 to l.Count - 1 do begin
  1702. NC := l[i];
  1703. if NC.Connected then begin
  1704. if NC is TNetServerClient then begin
  1705. if Not NC.IsMyselfServer then begin
  1706. lbNetConnections.Items.AddObject(Format('Client: IP:%s',[NC.ClientRemoteAddr]),NC);
  1707. end;
  1708. end else begin
  1709. if Not NC.IsMyselfServer then begin
  1710. lbNetConnections.Items.AddObject(Format('Server: IP:%s',[NC.ClientRemoteAddr]),NC);
  1711. end;
  1712. end;
  1713. end;
  1714. end;
  1715. Finally
  1716. lbNetConnections.Items.EndUpdate;
  1717. End;
  1718. finally
  1719. TNetData.NetData.NetConnections.UnlockList;
  1720. end;
  1721. end;
  1722. procedure TFRMWallet.UpdateBlockChainState;
  1723. Var isMining : boolean;
  1724. // hr : Int64;
  1725. i,mc : Integer;
  1726. s : String;
  1727. mtl : TList;
  1728. f, favg : real;
  1729. begin
  1730. UpdateNodeStatus;
  1731. mc := 0;
  1732. // hr := 0;
  1733. if Assigned(FNode) then begin
  1734. if FNode.Bank.BlocksCount>0 then begin
  1735. lblCurrentBlock.Caption := Inttostr(FNode.Bank.BlocksCount)+' (0..'+Inttostr(FNode.Bank.BlocksCount-1)+')'; ;
  1736. end else lblCurrentBlock.Caption := '(none)';
  1737. lblCurrentAccounts.Caption := Inttostr(FNode.Bank.AccountsCount);
  1738. lblCurrentBlockTime.Caption := UnixTimeToLocalElapsedTime(FNode.Bank.LastOperationBlock.timestamp);
  1739. lblOperationsPending.Caption := Inttostr(FNode.Operations.Count);
  1740. lblCurrentDifficulty.Caption := InttoHex(FNode.Operations.OperationBlock.compact_target,8);
  1741. favg := FNode.Bank.GetActualTargetSecondsAverage(CT_CalcNewTargetBlocksAverage);
  1742. f := (CT_NewLineSecondsAvg - favg) / CT_NewLineSecondsAvg;
  1743. lblTimeAverage.Caption := 'Last '+Inttostr(CT_CalcNewTargetBlocksAverage)+': '+FormatFloat('0.0',favg)+' sec. (Optimal '+Inttostr(CT_NewLineSecondsAvg)+'s) Deviation '+FormatFloat('0.00%',f*100);
  1744. if favg>=CT_NewLineSecondsAvg then begin
  1745. lblTimeAverage.Font.Color := clNavy;
  1746. end else begin
  1747. lblTimeAverage.Font.Color := clOlive;
  1748. end;
  1749. lblTimeAverageAux.Caption := Format('Last %d: %s sec. - %d: %s sec. - %d: %s sec. - %d: %s sec. - %d: %s sec.',[
  1750. CT_CalcNewTargetBlocksAverage * 2 ,FormatFloat('0.0',FNode.Bank.GetActualTargetSecondsAverage(CT_CalcNewTargetBlocksAverage * 2)),
  1751. ((CT_CalcNewTargetBlocksAverage * 3) DIV 2) ,FormatFloat('0.0',FNode.Bank.GetActualTargetSecondsAverage((CT_CalcNewTargetBlocksAverage * 3) DIV 2)),
  1752. ((CT_CalcNewTargetBlocksAverage DIV 4)*3),FormatFloat('0.0',FNode.Bank.GetActualTargetSecondsAverage(((CT_CalcNewTargetBlocksAverage DIV 4)*3))),
  1753. CT_CalcNewTargetBlocksAverage DIV 2,FormatFloat('0.0',FNode.Bank.GetActualTargetSecondsAverage(CT_CalcNewTargetBlocksAverage DIV 2)),
  1754. CT_CalcNewTargetBlocksAverage DIV 4,FormatFloat('0.0',FNode.Bank.GetActualTargetSecondsAverage(CT_CalcNewTargetBlocksAverage DIV 4))]);
  1755. end else begin
  1756. isMining := false;
  1757. lblCurrentBlock.Caption := '';
  1758. lblCurrentAccounts.Caption := '';
  1759. lblCurrentBlockTime.Caption := '';
  1760. lblOperationsPending.Caption := '';
  1761. lblCurrentDifficulty.Caption := '';
  1762. lblTimeAverage.Caption := '';
  1763. lblTimeAverageAux.Caption := '';
  1764. end;
  1765. if (Assigned(FPoolMiningServer)) And (FPoolMiningServer.Active) then begin
  1766. If FPoolMiningServer.ClientsCount>0 then begin
  1767. lblMinersClients.Caption := IntToStr(FPoolMiningServer.ClientsCount)+' connected JSON-RPC clients';
  1768. lblMinersClients.Font.Color := clNavy;
  1769. end else begin
  1770. lblMinersClients.Caption := 'No JSON-RPC clients';
  1771. lblMinersClients.Font.Color := clDkGray;
  1772. end;
  1773. MinersBlocksFound := FPoolMiningServer.ClientsWins;
  1774. end else begin
  1775. MinersBlocksFound := 0;
  1776. lblMinersClients.Caption := 'JSON-RPC server not active';
  1777. lblMinersClients.Font.Color := clRed;
  1778. end;
  1779. end;
  1780. procedure TFRMWallet.UpdateConfigChanged;
  1781. Var wa : Boolean;
  1782. i : Integer;
  1783. begin
  1784. tsLogs.TabVisible := FAppParams.ParamByName[CT_PARAM_ShowLogs].GetAsBoolean(false);
  1785. if (Not tsLogs.TabVisible) then begin
  1786. FLog.OnNewLog := Nil;
  1787. if PageControl.ActivePage = tsLogs then PageControl.ActivePage := tsMyAccounts;
  1788. end else FLog.OnNewLog := OnNewLog;
  1789. if FAppParams.ParamByName[CT_PARAM_SaveLogFiles].GetAsBoolean(false) then begin
  1790. if FAppParams.ParamByName[CT_PARAM_SaveDebugLogs].GetAsBoolean(false) then FLog.SaveTypes := CT_TLogTypes_ALL
  1791. else FLog.SaveTypes := CT_TLogTypes_DEFAULT;
  1792. FLog.FileName := TFolderHelper.GetPascalCoinDataFolder+PathDelim+'PascalCointWallet.log';
  1793. end else begin
  1794. FLog.SaveTypes := [];
  1795. FLog.FileName := '';
  1796. end;
  1797. if Assigned(FNode) then begin
  1798. wa := FNode.NetServer.Active;
  1799. FNode.NetServer.Port := FAppParams.ParamByName[CT_PARAM_InternetServerPort].GetAsInteger(CT_NetServer_Port);
  1800. FNode.NetServer.Active := wa;
  1801. FNode.Operations.BlockPayload := FAppParams.ParamByName[CT_PARAM_MinerName].GetAsString('');
  1802. FNode.NodeLogFilename := TFolderHelper.GetPascalCoinDataFolder+PathDelim+'blocks.log';
  1803. end;
  1804. if Assigned(FPoolMiningServer) then begin
  1805. if FPoolMiningServer.Port<>FAppParams.ParamByName[CT_PARAM_JSONRPCMinerServerPort].GetAsInteger(CT_JSONRPCMinerServer_Port) then begin
  1806. FPoolMiningServer.Active := false;
  1807. FPoolMiningServer.Port := FAppParams.ParamByName[CT_PARAM_JSONRPCMinerServerPort].GetAsInteger(CT_JSONRPCMinerServer_Port);
  1808. end;
  1809. FPoolMiningServer.Active :=FAppParams.ParamByName[CT_PARAM_JSONRPCMinerServerActive].GetAsBoolean(true);
  1810. FPoolMiningServer.UpdateAccountAndPayload(GetAccountKeyForMiner,FAppParams.ParamByName[CT_PARAM_MinerName].GetAsString(''));
  1811. end;
  1812. if Assigned(FRPCServer) then begin
  1813. FRPCServer.Active := FAppParams.ParamByName[CT_PARAM_JSONRPCEnabled].GetAsBoolean(false);
  1814. FRPCServer.ValidIPs := FAppParams.ParamByName[CT_PARAM_JSONRPCAllowedIPs].GetAsString('127.0.0.1');
  1815. end;
  1816. i := FAppParams.ParamByName[CT_PARAM_MinerPrivateKeyType].GetAsInteger(Integer(mpk_Random));
  1817. if (i>=Integer(Low(TMinerPrivatekey))) And (i<=Integer(High(TMinerPrivatekey))) then FMinerPrivateKeyType := TMinerPrivateKey(i)
  1818. else FMinerPrivateKeyType := mpk_Random;
  1819. ebHashRateBackBlocks.Text := IntToStr(FBlockChainGrid.HashRateAverageBlocksCount);
  1820. Case FBlockChainGrid.HashRateAs of
  1821. hr_Kilo : cbHashRateUnits.ItemIndex:=0;
  1822. hr_Mega : cbHashRateUnits.ItemIndex:=1;
  1823. hr_Giga : cbHashRateUnits.ItemIndex:=2;
  1824. hr_Tera : cbHashRateUnits.ItemIndex:=3;
  1825. else cbHashRateUnits.ItemIndex:=-1;
  1826. end;
  1827. end;
  1828. procedure TFRMWallet.UpdateConnectionStatus;
  1829. var errors : AnsiString;
  1830. begin
  1831. UpdateNodeStatus;
  1832. OnNetStatisticsChanged(Nil);
  1833. if Assigned(FNode) then begin
  1834. if FNode.IsBlockChainValid(errors) then begin
  1835. StatusBar.Panels[2].Text := Format('Last account time:%s',
  1836. [FormatDateTime('dd/mm/yyyy hh:nn:ss',UnivDateTime2LocalDateTime(UnixToUnivDateTime( FNode.Bank.LastOperationBlock.timestamp )))]);
  1837. end else begin
  1838. StatusBar.Panels[2].Text := 'NO BLOCKCHAIN: '+errors;
  1839. end;
  1840. end else begin
  1841. StatusBar.Panels[2].Text := '';
  1842. end;
  1843. end;
  1844. procedure TFRMWallet.UpdateNodeStatus;
  1845. Var status : AnsiString;
  1846. begin
  1847. If Not Assigned(FNode) then begin
  1848. lblNodeStatus.Font.Color := clRed;
  1849. lblNodeStatus.Caption := 'Initializing...';
  1850. end else begin
  1851. If FNode.IsReady(status) then begin
  1852. if TNetData.NetData.NetStatistics.ActiveConnections>0 then begin
  1853. lblNodeStatus.Font.Color := clGreen;
  1854. if TNetData.NetData.IsDiscoveringServers then begin
  1855. lblNodeStatus.Caption := 'Discovering servers';
  1856. end else if TNetData.NetData.IsGettingNewBlockChainFromClient then begin
  1857. lblNodeStatus.Caption := 'Obtaining new blockchain';
  1858. end else begin
  1859. lblNodeStatus.Caption := 'Running';
  1860. end;
  1861. end else begin
  1862. lblNodeStatus.Font.Color := clRed;
  1863. lblNodeStatus.Caption := 'Alone in the world...';
  1864. end;
  1865. end else begin
  1866. lblNodeStatus.Font.Color := clRed;
  1867. lblNodeStatus.Caption := status;
  1868. end;
  1869. end;
  1870. If Assigned(FBackgroundPanel) then begin
  1871. FBackgroundPanel.Font.Color:=lblNodeStatus.Font.Color;
  1872. FBackgroundPanel.Caption:='Please wait until finished: '+lblNodeStatus.Caption;
  1873. end;
  1874. end;
  1875. procedure TFRMWallet.UpdateOperations;
  1876. Var accn : Int64;
  1877. begin
  1878. accn := FAccountsGrid.AccountNumber(dgAccounts.Row);
  1879. FOperationsAccountGrid.AccountNumber := accn;
  1880. end;
  1881. procedure TFRMWallet.UpdatePrivateKeys;
  1882. Var i,last_i : Integer;
  1883. wk : TWalletKey;
  1884. s : AnsiString;
  1885. begin
  1886. If (Not Assigned(FOrderedAccountsKeyList)) And (Assigned(FNode)) Then begin
  1887. FOrderedAccountsKeyList := TOrderedAccountKeysList.Create(FNode.Bank.SafeBox,false);
  1888. end;
  1889. if (cbMyPrivateKeys.ItemIndex>=0) then last_i := PtrInt(cbMyPrivateKeys.Items.Objects[cbMyPrivateKeys.ItemIndex])
  1890. else last_i := -1;
  1891. cbMyPrivateKeys.items.BeginUpdate;
  1892. Try
  1893. cbMyPrivateKeys.Items.Clear;
  1894. For i:=0 to FWalletKeys.Count-1 do begin
  1895. wk := FWalletKeys.Key[i];
  1896. if assigned(FOrderedAccountsKeyList) then begin
  1897. FOrderedAccountsKeyList.AddAccountKey(wk.AccountKey);
  1898. end;
  1899. if (wk.Name='') then begin
  1900. s := 'Sha256='+TCrypto.ToHexaString( TCrypto.DoSha256( TAccountComp.AccountKey2RawString(wk.AccountKey) ) );
  1901. end else begin
  1902. s := wk.Name;
  1903. end;
  1904. if Not Assigned(wk.PrivateKey) then s := s + '(*)';
  1905. cbMyPrivateKeys.Items.AddObject(s,TObject(i));
  1906. end;
  1907. cbMyPrivateKeys.Sorted := true;
  1908. cbMyPrivateKeys.Sorted := false;
  1909. cbMyPrivateKeys.Items.InsertObject(0,'(All my private keys)',TObject(-1));
  1910. Finally
  1911. cbMyPrivateKeys.Items.EndUpdate;
  1912. End;
  1913. last_i := cbMyPrivateKeys.Items.IndexOfObject(TObject(last_i));
  1914. if last_i<0 then last_i := 0;
  1915. if cbMyPrivateKeys.Items.Count>last_i then cbMyPrivateKeys.ItemIndex := last_i
  1916. else if cbMyPrivateKeys.Items.Count>=0 then cbMyPrivateKeys.ItemIndex := 0;
  1917. end;
  1918. initialization
  1919. FRMWallet := Nil;
  1920. end.