1
+ package ledger
2
+
3
+ import (
4
+ "fmt"
5
+ "os"
6
+ "path/filepath"
7
+ "bufio"
8
+ "encoding/json"
9
+ )
10
+
11
+ type State struct {
12
+ Balances map [Account ]uint
13
+ txMempool []Tx
14
+
15
+ dbFile * os.File
16
+ }
17
+
18
+
19
+ func SyncState () (* State , error ) {
20
+ cwd , err := os .Getwd ()
21
+ if err != nil {
22
+ return nil , err
23
+ }
24
+
25
+ gen , err := loadGenesis (filepath .Join (cwd , "ledger" , "genesis.json" ))
26
+ if err != nil {
27
+ return nil , err
28
+ }
29
+
30
+ balances := make (map [Account ]uint )
31
+ for account , balance := range gen .Balances {
32
+ balances [account ] = balance
33
+ }
34
+
35
+ file , err := os .OpenFile (filepath .Join (cwd , "ledger" , "ledger.db" ), os .O_APPEND | os .O_RDWR , 0600 )
36
+ if err != nil {
37
+ return nil , err
38
+ }
39
+
40
+ scanner := bufio .NewScanner (file )
41
+
42
+ state := & State {balances , make ([]Tx , 0 ), file }
43
+
44
+ for scanner .Scan () {
45
+ if err := scanner .Err (); err != nil {
46
+ return nil , err
47
+ }
48
+
49
+ var transaction Tx
50
+ json .Unmarshal (scanner .Bytes (), & transaction )
51
+
52
+ if err := state .writeTransaction (transaction ); err != nil {
53
+ return nil , err
54
+ }
55
+ }
56
+
57
+ return state , nil
58
+ }
59
+
60
+ func (s * State ) writeTransaction (tx Tx ) error {
61
+ if s .Balances [tx .From ] < tx .Value {
62
+ return fmt .Errorf ("insufficient balance" )
63
+ }
64
+
65
+ s .Balances [tx .From ] -= tx .Value
66
+ s .Balances [tx .To ] += tx .Value
67
+
68
+ return nil
69
+ }
70
+
71
+ func (s * State ) Close () {
72
+ s .dbFile .Close ()
73
+ }
74
+
75
+ func (s * State ) WriteToLedger (tx Tx ) error {
76
+ if err := s .writeTransaction (tx ); err != nil {
77
+ return err
78
+ }
79
+
80
+ s .txMempool = append (s .txMempool , tx )
81
+
82
+ mempool := make ([]Tx , len (s .txMempool ))
83
+ copy (mempool , s .txMempool )
84
+
85
+ for i := 0 ; i < len (mempool ); i ++ {
86
+ txJson , err := json .Marshal (mempool [i ])
87
+ if err != nil {
88
+ return err
89
+ }
90
+
91
+ if _ , err = s .dbFile .Write (append (txJson , '\n' )); err != nil {
92
+ return err
93
+ }
94
+ s .txMempool = s .txMempool [1 :]
95
+ }
96
+
97
+ return nil
98
+ }
0 commit comments