├── .gitignore
├── BitcoinBlockChainExplorer.dpr
├── BitcoinBlockChainExplorer.dproj
├── BitcoinBlockChainExplorer.res
├── BlocksUnit.pas
├── CryptoVirtualTreeUnit.pas
├── LICENSE
├── MainFormUnit.dfm
├── MainFormUnit.pas
├── README.md
├── SeSHA256.pas
├── ThreadUnit.pas
├── asm.inc
├── datamodule.dfm
├── datamodule.pas
└── sample-config.ini
/.gitignore:
--------------------------------------------------------------------------------
1 | # Uncomment these types if you want even more clean repository. But be careful.
2 | # It can make harm to an existing project source. Read explanations below.
3 | #
4 | # Resource files are binaries containing manifest, project icon and version info.
5 | # They can not be viewed as text or compared by diff-tools. Consider replacing them with .rc files.
6 | #*.res
7 | #
8 | # Type library file (binary). In old Delphi versions it should be stored.
9 | # Since Delphi 2009 it is produced from .ridl file and can safely be ignored.
10 | #*.tlb
11 | #
12 | # Diagram Portfolio file. Used by the diagram editor up to Delphi 7.
13 | # Uncomment this if you are not using diagrams or use newer Delphi version.
14 | #*.ddp
15 | #
16 | # Visual LiveBindings file. Added in Delphi XE2.
17 | # Uncomment this if you are not using LiveBindings Designer.
18 | #*.vlb
19 | #
20 | # Deployment Manager configuration file for your project. Added in Delphi XE2.
21 | # Uncomment this if it is not mobile development and you do not use remote debug feature.
22 | #*.deployproj
23 | #
24 | # C++ object files produced when C/C++ Output file generation is configured.
25 | # Uncomment this if you are not using external objects (zlib library for example).
26 | #*.obj
27 | #
28 |
29 | # Delphi compiler-generated binaries (safe to delete)
30 | *.exe
31 | *.dll
32 | *.bpl
33 | *.bpi
34 | *.dcp
35 | *.so
36 | *.apk
37 | *.drc
38 | *.map
39 | *.dres
40 | *.rsm
41 | *.tds
42 | *.dcu
43 | *.lib
44 | *.a
45 | *.o
46 | *.ocx
47 |
48 | # Delphi autogenerated files (duplicated info)
49 | *.cfg
50 | *.hpp
51 | *Resource.rc
52 |
53 | # Delphi local files (user-specific info)
54 | *.local
55 | *.identcache
56 | *.projdata
57 | *.tvsconfig
58 | *.dsk
59 |
60 | # Delphi history and backups
61 | __history/
62 | __recovery/
63 | *.~*
64 |
65 | # Castalia statistics file (since XE7 Castalia is distributed with Delphi)
66 | *.stat
67 | Win32/Debug/config.ini
68 | config.ini
69 |
--------------------------------------------------------------------------------
/BitcoinBlockChainExplorer.dpr:
--------------------------------------------------------------------------------
1 | program BitcoinBlockChainExplorer;
2 |
3 | uses
4 | Vcl.Forms,
5 | MainFormUnit in 'MainFormUnit.pas' {MainForm},
6 | BlocksUnit in 'BlocksUnit.pas',
7 | SeSHA256 in 'SeSHA256.pas',
8 | ThreadUnit in 'ThreadUnit.pas';
9 |
10 | {$R *.res}
11 |
12 | begin
13 | Application.Initialize;
14 | Application.MainFormOnTaskbar := True;
15 | Application.CreateForm(TMainForm, MainForm);
16 | Application.Run;
17 |
18 | end.
19 |
--------------------------------------------------------------------------------
/BitcoinBlockChainExplorer.dproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {8C8DBE02-69FF-4E27-B31A-0D5AE8768554}
4 | 19.2
5 | VCL
6 | BitcoinBlockChainExplorer.dpr
7 | True
8 | Debug
9 | Win32
10 | 1
11 | Application
12 |
13 |
14 | true
15 |
16 |
17 | true
18 | Base
19 | true
20 |
21 |
22 | true
23 | Base
24 | true
25 |
26 |
27 | true
28 | Base
29 | true
30 |
31 |
32 | true
33 | Cfg_1
34 | true
35 | true
36 |
37 |
38 | true
39 | Cfg_1
40 | true
41 | true
42 |
43 |
44 | true
45 | Base
46 | true
47 |
48 |
49 | true
50 | Cfg_2
51 | true
52 | true
53 |
54 |
55 | true
56 | Cfg_2
57 | true
58 | true
59 |
60 |
61 | .\$(Platform)\$(Config)
62 | .\$(Platform)\$(Config)
63 | false
64 | false
65 | false
66 | false
67 | false
68 | RESTComponents;FireDAC;FireDACSqliteDriver;soaprtl;FireDACIBDriver;soapmidas;FireDACCommon;RESTBackendComponents;soapserver;CloudService;FireDACCommonDriver;inet;$(DCC_UsePackage)
69 | System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
70 | $(BDS)\bin\delphi_PROJECTICON.ico
71 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
72 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
73 | BitcoinBlockChainExplorer
74 |
75 |
76 | DBXSqliteDriver;IndyIPCommon;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;tethering;svnui;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;vcltouch;vcldb;bindcompfmx;svn;FireDACPgDriver;inetdb;DbxCommonDriver;fmx;fmxdae;xmlrtl;fmxobj;vclwinx;rtl;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;vclx;bindcomp;appanalytics;dsnap;IndyIPClient;bindcompvcl;VCLRESTComponents;dbxcds;VclSmp;adortl;vclie;bindengine;DBXMySQLDriver;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;fmxase;$(DCC_UsePackage)
77 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
78 | Debug
79 | true
80 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
81 | 1033
82 | $(BDS)\bin\default_app.manifest
83 |
84 |
85 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
86 | Debug
87 | true
88 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
89 | 1033
90 | $(BDS)\bin\default_app.manifest
91 |
92 |
93 | DEBUG;$(DCC_Define)
94 | true
95 | false
96 | true
97 | true
98 | true
99 |
100 |
101 | false
102 | true
103 | PerMonitor
104 |
105 |
106 | true
107 | PerMonitorV2
108 |
109 |
110 | false
111 | RELEASE;$(DCC_Define)
112 | 0
113 | 0
114 |
115 |
116 | true
117 | PerMonitor
118 |
119 |
120 | true
121 | PerMonitorV2
122 |
123 |
124 |
125 | MainSource
126 |
127 |
128 |
129 | dfm
130 |
131 |
132 |
133 |
134 |
135 |
136 | Cfg_2
137 | Base
138 |
139 |
140 | Base
141 |
142 |
143 | Cfg_1
144 | Base
145 |
146 |
147 |
148 | Delphi.Personality.12
149 | Application
150 |
151 |
152 |
153 | BitcoinBlockChainExplorer.dpr
154 |
155 |
156 |
157 |
158 |
159 | BitcoinBlockChainExplorer.exe
160 | true
161 |
162 |
163 |
164 |
165 | .\
166 | true
167 |
168 |
169 |
170 |
171 | 1
172 |
173 |
174 | Contents\MacOS
175 | 1
176 |
177 |
178 | 0
179 |
180 |
181 |
182 |
183 | classes
184 | 1
185 |
186 |
187 | classes
188 | 1
189 |
190 |
191 |
192 |
193 | res\xml
194 | 1
195 |
196 |
197 | res\xml
198 | 1
199 |
200 |
201 |
202 |
203 | library\lib\armeabi-v7a
204 | 1
205 |
206 |
207 |
208 |
209 | library\lib\armeabi
210 | 1
211 |
212 |
213 | library\lib\armeabi
214 | 1
215 |
216 |
217 |
218 |
219 | library\lib\armeabi-v7a
220 | 1
221 |
222 |
223 |
224 |
225 | library\lib\mips
226 | 1
227 |
228 |
229 | library\lib\mips
230 | 1
231 |
232 |
233 |
234 |
235 | library\lib\armeabi-v7a
236 | 1
237 |
238 |
239 | library\lib\arm64-v8a
240 | 1
241 |
242 |
243 |
244 |
245 | library\lib\armeabi-v7a
246 | 1
247 |
248 |
249 |
250 |
251 | res\drawable
252 | 1
253 |
254 |
255 | res\drawable
256 | 1
257 |
258 |
259 |
260 |
261 | res\values
262 | 1
263 |
264 |
265 | res\values
266 | 1
267 |
268 |
269 |
270 |
271 | res\values-v21
272 | 1
273 |
274 |
275 | res\values-v21
276 | 1
277 |
278 |
279 |
280 |
281 | res\values
282 | 1
283 |
284 |
285 | res\values
286 | 1
287 |
288 |
289 |
290 |
291 | res\drawable
292 | 1
293 |
294 |
295 | res\drawable
296 | 1
297 |
298 |
299 |
300 |
301 | res\drawable-xxhdpi
302 | 1
303 |
304 |
305 | res\drawable-xxhdpi
306 | 1
307 |
308 |
309 |
310 |
311 | res\drawable-xxxhdpi
312 | 1
313 |
314 |
315 | res\drawable-xxxhdpi
316 | 1
317 |
318 |
319 |
320 |
321 | res\drawable-ldpi
322 | 1
323 |
324 |
325 | res\drawable-ldpi
326 | 1
327 |
328 |
329 |
330 |
331 | res\drawable-mdpi
332 | 1
333 |
334 |
335 | res\drawable-mdpi
336 | 1
337 |
338 |
339 |
340 |
341 | res\drawable-hdpi
342 | 1
343 |
344 |
345 | res\drawable-hdpi
346 | 1
347 |
348 |
349 |
350 |
351 | res\drawable-xhdpi
352 | 1
353 |
354 |
355 | res\drawable-xhdpi
356 | 1
357 |
358 |
359 |
360 |
361 | res\drawable-mdpi
362 | 1
363 |
364 |
365 | res\drawable-mdpi
366 | 1
367 |
368 |
369 |
370 |
371 | res\drawable-hdpi
372 | 1
373 |
374 |
375 | res\drawable-hdpi
376 | 1
377 |
378 |
379 |
380 |
381 | res\drawable-xhdpi
382 | 1
383 |
384 |
385 | res\drawable-xhdpi
386 | 1
387 |
388 |
389 |
390 |
391 | res\drawable-xxhdpi
392 | 1
393 |
394 |
395 | res\drawable-xxhdpi
396 | 1
397 |
398 |
399 |
400 |
401 | res\drawable-xxxhdpi
402 | 1
403 |
404 |
405 | res\drawable-xxxhdpi
406 | 1
407 |
408 |
409 |
410 |
411 | res\drawable-small
412 | 1
413 |
414 |
415 | res\drawable-small
416 | 1
417 |
418 |
419 |
420 |
421 | res\drawable-normal
422 | 1
423 |
424 |
425 | res\drawable-normal
426 | 1
427 |
428 |
429 |
430 |
431 | res\drawable-large
432 | 1
433 |
434 |
435 | res\drawable-large
436 | 1
437 |
438 |
439 |
440 |
441 | res\drawable-xlarge
442 | 1
443 |
444 |
445 | res\drawable-xlarge
446 | 1
447 |
448 |
449 |
450 |
451 | res\values
452 | 1
453 |
454 |
455 | res\values
456 | 1
457 |
458 |
459 |
460 |
461 | 1
462 |
463 |
464 | Contents\MacOS
465 | 1
466 |
467 |
468 | 0
469 |
470 |
471 |
472 |
473 | Contents\MacOS
474 | 1
475 | .framework
476 |
477 |
478 | Contents\MacOS
479 | 1
480 | .framework
481 |
482 |
483 | 0
484 |
485 |
486 |
487 |
488 | 1
489 | .dylib
490 |
491 |
492 | 1
493 | .dylib
494 |
495 |
496 | 1
497 | .dylib
498 |
499 |
500 | Contents\MacOS
501 | 1
502 | .dylib
503 |
504 |
505 | Contents\MacOS
506 | 1
507 | .dylib
508 |
509 |
510 | 0
511 | .dll;.bpl
512 |
513 |
514 |
515 |
516 | 1
517 | .dylib
518 |
519 |
520 | 1
521 | .dylib
522 |
523 |
524 | 1
525 | .dylib
526 |
527 |
528 | Contents\MacOS
529 | 1
530 | .dylib
531 |
532 |
533 | Contents\MacOS
534 | 1
535 | .dylib
536 |
537 |
538 | 0
539 | .bpl
540 |
541 |
542 |
543 |
544 | 0
545 |
546 |
547 | 0
548 |
549 |
550 | 0
551 |
552 |
553 | 0
554 |
555 |
556 | 0
557 |
558 |
559 | Contents\Resources\StartUp\
560 | 0
561 |
562 |
563 | Contents\Resources\StartUp\
564 | 0
565 |
566 |
567 | 0
568 |
569 |
570 |
571 |
572 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
573 | 1
574 |
575 |
576 |
577 |
578 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
579 | 1
580 |
581 |
582 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
583 | 1
584 |
585 |
586 |
587 |
588 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
589 | 1
590 |
591 |
592 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
593 | 1
594 |
595 |
596 |
597 |
598 | 1
599 |
600 |
601 | 1
602 |
603 |
604 | 1
605 |
606 |
607 |
608 |
609 | 1
610 |
611 |
612 | 1
613 |
614 |
615 | 1
616 |
617 |
618 |
619 |
620 | 1
621 |
622 |
623 | 1
624 |
625 |
626 | 1
627 |
628 |
629 |
630 |
631 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
632 | 1
633 |
634 |
635 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
636 | 1
637 |
638 |
639 |
640 |
641 | 1
642 |
643 |
644 | 1
645 |
646 |
647 | 1
648 |
649 |
650 |
651 |
652 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
653 | 1
654 |
655 |
656 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
657 | 1
658 |
659 |
660 |
661 |
662 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
663 | 1
664 |
665 |
666 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
667 | 1
668 |
669 |
670 |
671 |
672 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
673 | 1
674 |
675 |
676 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
677 | 1
678 |
679 |
680 |
681 |
682 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
683 | 1
684 |
685 |
686 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
687 | 1
688 |
689 |
690 |
691 |
692 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
693 | 1
694 |
695 |
696 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
697 | 1
698 |
699 |
700 |
701 |
702 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
703 | 1
704 |
705 |
706 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
707 | 1
708 |
709 |
710 |
711 |
712 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
713 | 1
714 |
715 |
716 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
717 | 1
718 |
719 |
720 |
721 |
722 | 1
723 |
724 |
725 | 1
726 |
727 |
728 | 1
729 |
730 |
731 |
732 |
733 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
734 | 1
735 |
736 |
737 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
738 | 1
739 |
740 |
741 |
742 |
743 | 1
744 |
745 |
746 | 1
747 |
748 |
749 | 1
750 |
751 |
752 |
753 |
754 | 1
755 |
756 |
757 | 1
758 |
759 |
760 | 1
761 |
762 |
763 |
764 |
765 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
766 | 1
767 |
768 |
769 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
770 | 1
771 |
772 |
773 |
774 |
775 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
776 | 1
777 |
778 |
779 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
780 | 1
781 |
782 |
783 |
784 |
785 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
786 | 1
787 |
788 |
789 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
790 | 1
791 |
792 |
793 |
794 |
795 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
796 | 1
797 |
798 |
799 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
800 | 1
801 |
802 |
803 |
804 |
805 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
806 | 1
807 |
808 |
809 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
810 | 1
811 |
812 |
813 |
814 |
815 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
816 | 1
817 |
818 |
819 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
820 | 1
821 |
822 |
823 |
824 |
825 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
826 | 1
827 |
828 |
829 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
830 | 1
831 |
832 |
833 |
834 |
835 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
836 | 1
837 |
838 |
839 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
840 | 1
841 |
842 |
843 |
844 |
845 | 1
846 |
847 |
848 | 1
849 |
850 |
851 |
852 |
853 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
854 | 1
855 |
856 |
857 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
858 | 1
859 |
860 |
861 |
862 |
863 | 1
864 |
865 |
866 | 1
867 |
868 |
869 |
870 |
871 | ..\
872 | 1
873 |
874 |
875 | ..\
876 | 1
877 |
878 |
879 |
880 |
881 | 1
882 |
883 |
884 | 1
885 |
886 |
887 | 1
888 |
889 |
890 |
891 |
892 | ..\$(PROJECTNAME).launchscreen
893 | 64
894 |
895 |
896 | ..\$(PROJECTNAME).launchscreen
897 | 64
898 |
899 |
900 |
901 |
902 | 1
903 |
904 |
905 | 1
906 |
907 |
908 | 1
909 |
910 |
911 |
912 |
913 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
914 | 1
915 |
916 |
917 |
918 |
919 | ..\
920 | 1
921 |
922 |
923 | ..\
924 | 1
925 |
926 |
927 |
928 |
929 | Contents
930 | 1
931 |
932 |
933 | Contents
934 | 1
935 |
936 |
937 |
938 |
939 | Contents\Resources
940 | 1
941 |
942 |
943 | Contents\Resources
944 | 1
945 |
946 |
947 |
948 |
949 | library\lib\armeabi-v7a
950 | 1
951 |
952 |
953 | library\lib\arm64-v8a
954 | 1
955 |
956 |
957 | 1
958 |
959 |
960 | 1
961 |
962 |
963 | 1
964 |
965 |
966 | 1
967 |
968 |
969 | Contents\MacOS
970 | 1
971 |
972 |
973 | Contents\MacOS
974 | 1
975 |
976 |
977 | 0
978 |
979 |
980 |
981 |
982 | library\lib\armeabi-v7a
983 | 1
984 |
985 |
986 |
987 |
988 | 1
989 |
990 |
991 | 1
992 |
993 |
994 |
995 |
996 | Assets
997 | 1
998 |
999 |
1000 | Assets
1001 | 1
1002 |
1003 |
1004 |
1005 |
1006 | Assets
1007 | 1
1008 |
1009 |
1010 | Assets
1011 | 1
1012 |
1013 |
1014 |
1015 |
1016 |
1017 |
1018 |
1019 |
1020 |
1021 |
1022 |
1023 |
1024 |
1025 |
1026 | True
1027 | False
1028 |
1029 |
1030 | 12
1031 |
1032 |
1033 |
1034 |
1035 |
1036 |
--------------------------------------------------------------------------------
/BitcoinBlockChainExplorer.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ildemartinez/Delphi-Component-for-BlockChain-Dat-Files/2e01557fd4537d9375bd148183134b34bf8e9b5f/BitcoinBlockChainExplorer.res
--------------------------------------------------------------------------------
/BlocksUnit.pas:
--------------------------------------------------------------------------------
1 | unit BlocksUnit;
2 |
3 | interface
4 |
5 | uses
6 | System.Classes,
7 | System.Contnrs,
8 | Generics.Collections,
9 |
10 | SeSHA256;
11 |
12 | type
13 | TCrypto = (tcBitcoin);
14 | TNet = (tnMainNet, tnTestNet);
15 |
16 | TBlockChainFiles = class;
17 |
18 | TBlockFile = class(TObject)
19 | parent: TBlockChainFiles;
20 | aFileName: string;
21 | aBlockNumber: integer;
22 | afs: TBufferedFileStream;
23 | end;
24 |
25 | TBlockChainFiles = class(TList)
26 |
27 | end;
28 |
29 | TBlockHeader = record
30 | versionNumber: UInt32;
31 | aPreviousBlockHash: T32; // reverse please
32 | aMerkleRoot: T32; // reverse please
33 | time: UInt32; // UnixTime
34 | DifficultyTarget: UInt32;
35 | nonce: UInt32;
36 | end;
37 |
38 | TInput = class(TObject)
39 | aTXID: T32;
40 | aVOUT: UInt32;
41 | CoinBaseLength: uint64;
42 | CoinBase: PByte;
43 |
44 | destructor Destroy; override;
45 | end;
46 |
47 | TOutput = class(TObject)
48 | nValue: uint64;
49 | OutputScriptLength: uint64;
50 | OutputScript: PByte;
51 |
52 | destructor Destroy; override;
53 | end;
54 |
55 | TInputs = class(TObjectList)
56 | private
57 | function GetInput(index: integer): TInput;
58 | public
59 | function NewInput: TInput;
60 | property items[index: integer]: TInput read GetInput; default;
61 | end;
62 |
63 | TOutputs = class(TObjectList)
64 | private
65 | function GetOutput(index: integer): TOutput;
66 | public
67 | function NewOutput: TOutput;
68 | property items[index: integer]: TOutput read GetOutput; default;
69 | end;
70 |
71 | TTransaction = class(TObject)
72 | version: UInt32;
73 | inputs: TInputs;
74 | outputs: TOutputs;
75 |
76 | public
77 | constructor Create;
78 | destructor Destroy; override;
79 | end;
80 |
81 | TBlockTransactions = class(TObjectList)
82 | private
83 | function GetTransaction(index: integer): TTransaction;
84 | public
85 | function NewTransaction: TTransaction;
86 | property items[index: integer]: TTransaction read GetTransaction; default;
87 | end;
88 |
89 | TBlockRecord = class(TObject)
90 | nblock: uint64;
91 | blocktype: TCrypto;
92 | network: TNet;
93 |
94 | headerLenght: UInt32;
95 | hash: string;
96 | header: TBlockHeader;
97 | transactions: TBlockTransactions;
98 |
99 | ninputs, noutputs: uint64;
100 |
101 | public
102 | constructor Create;
103 | destructor Destroy; override;
104 | end;
105 |
106 | TStartFileBlockFoundNotify = procedure(const aBlockFiles: TList) of object;
107 | TFoundFileBlockNotify = procedure(const aBlockFile: TBlockFile; var next: boolean) of object;
108 | TEndFilesBlockFoundNotify = procedure(const aBlockFiles: tstringlist) of object;
109 |
110 | TFoundBlockNotify = procedure(const aBlock: TBlockRecord; var findnext: boolean) of object;
111 | TBlockProcessStepNotify = procedure(const aPos, asize: int64) of object;
112 |
113 | TBlocks = class(tthread)
114 | private
115 | // File block events
116 | fOnStartProcessFiles: TStartFileBlockFoundNotify;
117 | fOnAfterFileBlockProcessed: TFoundFileBlockNotify;
118 |
119 | fOnMagicBlockFound: TFoundBlockNotify;
120 | fBlockProcessStep: TBlockProcessStepNotify;
121 | // fEndProcessBlockFile: TEndProcessBlockFile;
122 | fOnEndProc: TNotifyEvent;
123 | fOnStartProc: TNotifyEvent;
124 | fOnBeforeFileBlockProcess: TFoundFileBlockNotify;
125 |
126 | procedure InternalProcessBlock(const aBlockFile: TBlockFile);
127 | public
128 | aBlockChainFiles: TBlockChainFiles;
129 | BlocksDir: string;
130 | aBlocksDirectory: string;
131 |
132 | procedure Execute; override;
133 |
134 | // Inicio y fin del parseo
135 | property OnStartingParsingBlockfiles: TNotifyEvent read fOnStartProc write fOnStartProc;
136 | property OnFinishedParsingBlockFiles: TNotifyEvent read fOnEndProc write fOnEndProc;
137 |
138 | // Start process all files
139 | property OnStartProcessFiles: TStartFileBlockFoundNotify read fOnStartProcessFiles write fOnStartProcessFiles;
140 |
141 | // before process a file
142 | property OnBeforeFileBlockProcess: TFoundFileBlockNotify read fOnBeforeFileBlockProcess write fOnBeforeFileBlockProcess;
143 |
144 | // after a processed file
145 | property OnAfterFileBlockProcessed: TFoundFileBlockNotify read fOnAfterFileBlockProcessed write fOnAfterFileBlockProcessed;
146 |
147 | // Block found
148 | property OnMagicBlockFound: TFoundBlockNotify read fOnMagicBlockFound write fOnMagicBlockFound;
149 |
150 | property OnBlockProcessStep: TBlockProcessStepNotify read fBlockProcessStep write fBlockProcessStep;
151 | end;
152 |
153 | implementation
154 |
155 | uses
156 | WinApi.Windows,
157 | SysUtils, dialogs, dateutils,
158 | MainFormUnit, System.hash,
159 | inifiles;
160 |
161 | procedure TBlocks.Execute;
162 | var
163 | searchResult: TSearchRec;
164 | aBlockFile: TBlockFile;
165 |
166 | aBlockFiles: TList;
167 | aBlockFil: string;
168 |
169 | next: boolean;
170 | files: string;
171 | begin
172 |
173 | aBlockChainFiles := TBlockChainFiles.Create;
174 |
175 | // Start parsing component
176 | if Assigned(OnStartingParsingBlockfiles) then
177 | Synchronize(
178 | procedure
179 | begin
180 | OnStartingParsingBlockfiles(self);
181 | end);
182 |
183 | SetCurrentDir(aBlocksDirectory);
184 |
185 | files := 'blk?????.dat';
186 | // files := 'blk00074.dat';
187 |
188 | if findfirst(files, faAnyFile, searchResult) = 0 then
189 | begin
190 | aBlockFiles := TList.Create;
191 |
192 | repeat
193 | aBlockFiles.Add(aBlocksDirectory + '\' + searchResult.Name);
194 | until findnext(searchResult) <> 0;
195 |
196 | // Must free up resources used by these successful finds
197 | System.SysUtils.FindClose(searchResult);
198 |
199 | // Start parsing all files
200 | if Assigned(OnStartProcessFiles) then
201 | Synchronize(
202 | procedure
203 | begin
204 | OnStartProcessFiles(aBlockFiles);
205 | end);
206 |
207 | for aBlockFil in aBlockFiles do
208 | begin
209 |
210 | aBlockFile := TBlockFile.Create;
211 | aBlockFile.parent := aBlockChainFiles;
212 | aBlockChainFiles.Add(aBlockFile);
213 | aBlockFile.aFileName := aBlockFil;
214 | aBlockFile.aBlockNumber := aBlockFiles.IndexOf(aBlockFil) + 1;
215 |
216 | // Start parsing a file
217 | if Assigned(fOnBeforeFileBlockProcess) then
218 | Synchronize(
219 | procedure
220 | begin
221 | fOnBeforeFileBlockProcess(aBlockFile, next);
222 | end);
223 |
224 | aBlockFile.afs := TBufferedFileStream.Create(aBlockFile.aFileName, fmOpenRead);
225 | try
226 | InternalProcessBlock(aBlockFile);
227 | finally
228 | aBlockFile.afs.Free;
229 | end;
230 |
231 | if Assigned(OnAfterFileBlockProcessed) then
232 | Synchronize(
233 | procedure
234 | begin
235 | OnAfterFileBlockProcessed(aBlockFile, next);
236 | end);
237 |
238 | aBlockFile.Free;
239 |
240 | if next = false then
241 | break;
242 | end;
243 |
244 | aBlockFiles.Free;
245 | end;
246 |
247 | if Assigned(OnFinishedParsingBlockFiles) then
248 | Synchronize(
249 | procedure
250 | begin
251 | OnFinishedParsingBlockFiles(self);
252 | end);
253 | end;
254 |
255 | procedure TBlocks.InternalProcessBlock(const aBlockFile: TBlockFile);
256 | var
257 | state, car: byte;
258 | aBlock: TBlockRecord;
259 | cont: boolean;
260 | aTransaction: TTransaction;
261 | aseq: longword;
262 | aInput: TInput;
263 | aOutput: TOutput;
264 |
265 | tb: THeader;
266 | var
267 | alocktime: UInt32;
268 | txCount, k: uint64;
269 |
270 | function ReadVarValue: uint64;
271 | var
272 | atxCount: UInt8;
273 | atxCount2: UInt16;
274 | atxCount4: UInt32;
275 | begin
276 | aBlockFile.afs.Read(atxCount, 1);
277 | if atxCount < $FD then
278 | result := atxCount
279 | else
280 | case atxCount of
281 | $FD:
282 | begin
283 | aBlockFile.afs.Read(atxCount2, 2);
284 | result := atxCount2;
285 | end;
286 | $FE:
287 | begin
288 | aBlockFile.afs.Read(atxCount4, 4);
289 | result := atxCount4;
290 | end;
291 | $FF:
292 | aBlockFile.afs.Read(result, 8);
293 | end;
294 |
295 | end;
296 |
297 | begin
298 | state := 0;
299 | cont := true;
300 |
301 | while (cont = true) and (aBlockFile.afs.Read(car, 1) = 1) do
302 | begin
303 |
304 | case state of
305 | 0:
306 | if car = $F9 then
307 | inc(state);
308 | 1:
309 | if car = $BE then
310 | inc(state)
311 | else
312 | state := 0;
313 | 2:
314 | if car = $B4 then
315 | inc(state)
316 | else
317 | state := 0;
318 | 3:
319 | if car = $D9 then
320 | begin
321 |
322 | if Assigned(OnBlockProcessStep) then
323 | Synchronize(
324 | procedure
325 | begin
326 | OnBlockProcessStep(aBlockFile.afs.Position, aBlockFile.afs.Size);
327 | end);
328 |
329 | aBlock := TBlockRecord.Create;
330 |
331 | aBlockFile.afs.Read(aBlock.headerLenght, 4);
332 |
333 | // Read the header fields
334 | aBlockFile.afs.Read(aBlock.header, HEADERSIZE);
335 |
336 | // Re-read the header to calculate hash
337 | aBlockFile.afs.Seek(-HEADERSIZE, soCurrent);
338 | aBlockFile.afs.Read(tb, HEADERSIZE);
339 |
340 | // double header hash
341 | aBlock.hash := reversehash(SHA256ToStr(CalcSHA256(SHA256ToBinaryStr(CalcHeaderSHA256(tb)))));
342 |
343 | // tx count
344 | txCount := ReadVarValue;
345 |
346 | while (txCount > 0) do
347 | begin
348 | aTransaction := aBlock.transactions.NewTransaction;
349 |
350 | // Read the transaction version
351 | aBlockFile.afs.Read(aTransaction.version, 4);
352 | // Read the inputs
353 | aBlock.ninputs := ReadVarValue;
354 |
355 | if aBlock.ninputs > 0 then
356 | for k := 0 to aBlock.ninputs - 1 do
357 | begin
358 | aInput := aTransaction.inputs.NewInput;
359 |
360 | aBlockFile.afs.Read(aInput.aTXID, 32);
361 | aBlockFile.afs.Read(aInput.aVOUT, 4);
362 |
363 | aInput.CoinBaseLength := ReadVarValue;
364 |
365 | GetMem(aInput.CoinBase, aInput.CoinBaseLength);
366 | aBlockFile.afs.Read(aInput.CoinBase^, aInput.CoinBaseLength);
367 |
368 | // No need store the seq
369 | aBlockFile.afs.Read(aseq, 4);
370 | end;
371 |
372 | // tx out count
373 | aBlock.noutputs := ReadVarValue;
374 |
375 | if aBlock.noutputs > 0 then
376 | for k := 0 to aBlock.noutputs - 1 do
377 | begin
378 | aOutput := aTransaction.outputs.NewOutput;
379 |
380 | aBlockFile.afs.Read(aOutput.nValue, 8); // in satoshis
381 |
382 | aOutput.OutputScriptLength := ReadVarValue;
383 |
384 | GetMem(aOutput.OutputScript, aOutput.OutputScriptLength);
385 | aBlockFile.afs.Read(aOutput.OutputScript^, aOutput.OutputScriptLength);
386 | end;
387 |
388 | aBlockFile.afs.Read(alocktime, 4);
389 | dec(txCount);
390 | end;
391 |
392 | // Fire the block found event
393 | if Assigned(OnMagicBlockFound) then
394 | Synchronize(
395 | procedure
396 | begin
397 | OnMagicBlockFound(aBlock, cont);
398 | end);
399 |
400 | // Free the block so user must copy or use it and forget
401 | aBlock.Free;
402 |
403 | state := 0;
404 | end;
405 |
406 | end;
407 |
408 | end;
409 |
410 | end;
411 |
412 | { TBlockRecord }
413 |
414 | constructor TBlockRecord.Create;
415 | begin
416 | transactions := TBlockTransactions.Create;
417 | end;
418 |
419 | destructor TBlockRecord.Destroy;
420 | begin
421 | transactions.Free;
422 |
423 | inherited;
424 | end;
425 |
426 | { TBlockTransactions }
427 |
428 | function TBlockTransactions.GetTransaction(index: integer): TTransaction;
429 | begin
430 | result := inherited items[index] as TTransaction;
431 | end;
432 |
433 | function TBlockTransactions.NewTransaction: TTransaction;
434 | begin
435 | result := TTransaction.Create;
436 | self.Add(result);
437 | end;
438 |
439 | { TTransaction }
440 |
441 | constructor TTransaction.Create;
442 | begin
443 | inputs := TInputs.Create;
444 | outputs := TOutputs.Create;
445 | end;
446 |
447 | destructor TTransaction.Destroy;
448 | begin
449 | inputs.Free;
450 | outputs.Free;
451 | end;
452 |
453 | { TOutputs }
454 |
455 | function TOutputs.GetOutput(index: integer): TOutput;
456 | begin
457 | result := TOutput(inherited items[index]);
458 | end;
459 |
460 | function TOutputs.NewOutput: TOutput;
461 | begin
462 | result := TOutput.Create;
463 | self.Add(result);
464 | end;
465 |
466 | { TInputs }
467 |
468 | function TInputs.GetInput(index: integer): TInput;
469 | begin
470 | result := TInput(inherited items[index]);
471 | end;
472 |
473 | function TInputs.NewInput: TInput;
474 | begin
475 | result := TInput.Create;
476 | self.Add(result);
477 | end;
478 |
479 | destructor TInput.Destroy;
480 | begin
481 | FreeMem(CoinBase);
482 |
483 | inherited;
484 | end;
485 |
486 | destructor TOutput.Destroy;
487 | begin
488 | FreeMem(OutputScript);
489 |
490 | inherited;
491 | end;
492 |
493 | end.
494 |
--------------------------------------------------------------------------------
/CryptoVirtualTreeUnit.pas:
--------------------------------------------------------------------------------
1 | unit CryptoVirtualTreeUnit;
2 |
3 | interface
4 |
5 | uses
6 | System.Classes, virtualtrees;
7 |
8 | type
9 | TCryptoVirtualTree = class(TCustomVirtualStringTree)
10 |
11 | public
12 | constructor Create(AOwner: TComponent); override;
13 | end;
14 |
15 | implementation
16 |
17 | { TCryptoVirtualTree }
18 |
19 | constructor TCryptoVirtualTree.Create(AOwner: TComponent);
20 | var
21 | aNode: PVirtualNode;
22 | begin
23 | inherited;
24 |
25 | aNode := self.AddChild(nil);
26 |
27 | AddChild(aNode);
28 | AddChild(aNode);
29 | AddChild(aNode);
30 | AddChild(aNode);
31 |
32 | end;
33 |
34 | end.
35 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Software Tools for Makers
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/MainFormUnit.dfm:
--------------------------------------------------------------------------------
1 | object MainForm: TMainForm
2 | Left = 0
3 | Top = 0
4 | Caption = 'CryptoLab'
5 | ClientHeight = 665
6 | ClientWidth = 1211
7 | Color = clBtnFace
8 | Font.Charset = DEFAULT_CHARSET
9 | Font.Color = clWindowText
10 | Font.Height = -11
11 | Font.Name = 'Tahoma'
12 | Font.Style = []
13 | FormStyle = fsMDIForm
14 | OldCreateOrder = False
15 | OnCreate = FormCreate
16 | PixelsPerInch = 96
17 | TextHeight = 13
18 | object Memo1: TMemo
19 | Left = 104
20 | Top = 31
21 | Width = 770
22 | Height = 337
23 | Font.Charset = DEFAULT_CHARSET
24 | Font.Color = clWindowText
25 | Font.Height = -9
26 | Font.Name = 'Tahoma'
27 | Font.Style = []
28 | ParentFont = False
29 | TabOrder = 0
30 | end
31 | object Button2: TButton
32 | Left = 48
33 | Top = 374
34 | Width = 75
35 | Height = 25
36 | Caption = 'Button2'
37 | TabOrder = 1
38 | OnClick = Button2Click
39 | end
40 | object Button1: TButton
41 | Left = 368
42 | Top = 424
43 | Width = 75
44 | Height = 25
45 | Caption = 'Button1'
46 | TabOrder = 2
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/MainFormUnit.pas:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ildemartinez/Delphi-Component-for-BlockChain-Dat-Files/2e01557fd4537d9375bd148183134b34bf8e9b5f/MainFormUnit.pas
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Delphi Component for Bitcoin BlockChain parse Dat Files
2 | This is a Delphi component for reading the dat files from Blockchain. The idea is a high performance event driven component to parse blockchain files from several criptocurrencies. Lets start with the Bitcoin one!
3 |
4 | Here is released the component and the application to test it..... on dev process of course!
5 |
6 | Hashing sha256 functions from https://github.com/dxeoane/secrypt
7 |
--------------------------------------------------------------------------------
/SeSHA256.pas:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ildemartinez/Delphi-Component-for-BlockChain-Dat-Files/2e01557fd4537d9375bd148183134b34bf8e9b5f/SeSHA256.pas
--------------------------------------------------------------------------------
/ThreadUnit.pas:
--------------------------------------------------------------------------------
1 | unit ThreadUnit;
2 |
3 | interface
4 |
5 | implementation
6 |
7 | end.
8 |
--------------------------------------------------------------------------------
/asm.inc:
--------------------------------------------------------------------------------
1 | {$IFDEF i386}
2 |
3 | {$IFDEF FPC}
4 | {$ASMMODE intel}
5 | {$ENDIF}
6 |
7 | function ror(x: Cardinal; y: Byte): Cardinal; assembler;
8 | asm
9 | mov cl,dl
10 | ror eax,cl
11 | end;
12 |
13 | function rol(x: Cardinal; y: Byte): Cardinal; assembler;
14 | asm
15 | mov cl,dl
16 | rol eax,cl
17 | end;
18 |
19 | function bswap(x: Cardinal): Cardinal; assembler;
20 | asm
21 | bswap eax
22 | end;
23 |
24 | function swap64(x: int64): int64; assembler;
25 | asm
26 | mov edx,dword ptr[x]
27 | mov eax,dword ptr[x+4]
28 | bswap edx
29 | bswap eax
30 | end;
31 | {$ELSE}
32 | function ror(x: Cardinal; y: Byte): Cardinal;
33 | begin
34 | ror:=
35 | (x shr y) +
36 | (x shl (32-y));
37 | end;
38 |
39 | function rol(x: Cardinal; y: Byte): Cardinal;
40 | begin
41 | rol:=
42 | (x shl y) +
43 | (x shr (32-y));
44 | end;
45 |
46 | function bswap(x: Cardinal): Cardinal;
47 | begin
48 | bswap:=
49 | ((x and $000000FF) shl 24) +
50 | ((x and $0000FF00) shl 8) +
51 | ((x and $00FF0000) shr 8) +
52 | ((x and $FF000000) shr 24);
53 | end;
54 |
55 | function swap64(x: uint64): uint64;
56 | begin
57 | swap64:=
58 | ((x and $00000000000000FF) shl 56) +
59 | ((x and $000000000000FF00) shl 40) +
60 | ((x and $0000000000FF0000) shl 24) +
61 | ((x and $00000000FF000000) shl 8) +
62 | ((x and $000000FF00000000) shr 8) +
63 | ((x and $0000FF0000000000) shr 24) +
64 | ((x and $00FF000000000000) shr 40) +
65 | ((x and $FF00000000000000) shr 56);
66 | end;
67 | {$ENDIF}
--------------------------------------------------------------------------------
/datamodule.dfm:
--------------------------------------------------------------------------------
1 | object dm: Tdm
2 | OldCreateOrder = False
3 | Height = 183
4 | Width = 265
5 | object dbconnection: TFDConnection
6 | Params.Strings = (
7 | 'ConnectionDef=btcblockchaindb')
8 | LoginPrompt = False
9 | Left = 57
10 | Top = 20
11 | end
12 | object aQuery: TFDQuery
13 | Connection = dbconnection
14 | SQL.Strings = (
15 | '')
16 | Left = 144
17 | Top = 88
18 | end
19 | object FDPhysPgDriverLink1: TFDPhysPgDriverLink
20 | Left = 56
21 | Top = 111
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/datamodule.pas:
--------------------------------------------------------------------------------
1 | unit datamodule;
2 |
3 | interface
4 |
5 | uses
6 | System.SysUtils, System.Classes, FireDAC.Stan.Intf, FireDAC.Stan.Option,
7 | FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf, FireDAC.Stan.Def,
8 | FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys, FireDAC.Phys.PG,
9 | FireDAC.Phys.PGDef, FireDAC.VCLUI.Wait, Data.DB, FireDAC.Comp.Client,
10 | BlocksUnit, FireDAC.Stan.Param, FireDAC.DatS, FireDAC.DApt.Intf, FireDAC.DApt,
11 | FireDAC.Comp.DataSet;
12 |
13 | type
14 | Tdm = class(TDataModule)
15 | dbconnection: TFDConnection;
16 | aQuery: TFDQuery;
17 | FDPhysPgDriverLink1: TFDPhysPgDriverLink;
18 | private
19 | { Private declarations }
20 | public
21 | { Public declarations }
22 | function InsertBlock(aBlock: TBlockRecord): boolean;
23 | end;
24 |
25 | var
26 | dm: Tdm;
27 |
28 | implementation
29 |
30 | uses
31 | System.DateUtils,
32 | SeSHA256;
33 |
34 | {%CLASSGROUP 'Vcl.Controls.TControl'}
35 | {$R *.dfm}
36 | { Tdm }
37 |
38 | function Tdm.InsertBlock(aBlock: TBlockRecord): boolean;
39 | var
40 | aPreviousBlock, aMerkleRoot, aNextBlock: string;
41 | aTime: TDateTime;
42 | begin
43 | aQuery.SQL.Clear;
44 |
45 | aPreviousBlock := T32ToString(aBlock.header.aPreviousBlockHash);
46 | {
47 | if aPreviousBlock = 0 then
48 | begin
49 | aPreviousId := 0;
50 | end
51 | else
52 | begin
53 |
54 | end; }
55 |
56 | aMerkleRoot := T32ToString(aBlock.header.aMerkleRoot);
57 | aTime := UnixToDateTime(aBlock.header.time);
58 |
59 | aQuery.SQL.Add
60 | (format('insert into blocks (hash,amerkleroot,time) values (''%s'',''%s'',''%s'')',
61 | [aBlock.hash, aMerkleRoot, DateTimeToStr(aTime)]));
62 |
63 | aQuery.ExecSQL;
64 | aQuery.Close;
65 | end;
66 |
67 | end.
68 |
--------------------------------------------------------------------------------
/sample-config.ini:
--------------------------------------------------------------------------------
1 | [File]
2 | BlockFilePath=
3 |
4 | [Postgresql]
5 | host=
6 | db=
7 | port=
8 | user=
9 | password=
10 |
--------------------------------------------------------------------------------