@@ -60,7 +60,7 @@ public void addTxn(Txn newTx, int idx) {
6060 if (outGraph .get (key ) == null ) {
6161 outGraph .put (key , new HashSet <String >());
6262 }
63-
63+
6464 for (int i =0 ; i <newTx .outputs .size (); i ++) {
6565 String val = newTx .txnHash + ":" + String .valueOf (i ) + "," + newTx .outputs .get (i ).userAccount ;
6666 Set <String > outs = outGraph .get (key );
@@ -115,8 +115,8 @@ public void markDoubleSpend(List<Hash> order, HashMap<String, Hash> txnToTangleM
115115 }
116116 }
117117
118- public void markTheLaterAsDoubleSpend (List <Hash > order , HashMap <String , Hash > txnToTangleMap , Set <String > valSet ) {
119- Map <String , Integer > toSort = new ConcurrentHashMap <>();
118+ private void markTheLaterAsDoubleSpend (List <Hash > order , HashMap <String , Hash > txnToTangleMap , Set <String > valSet ) {
119+ Map <String , Integer > toSort = new ConcurrentHashMap <>();
120120 for (String out : valSet ) {
121121 Hash h = txnToTangleMap .get (out );
122122 int pos = order .indexOf (h );
@@ -134,18 +134,82 @@ public void markTheLaterAsDoubleSpend(List<Hash> order, HashMap<String, Hash> tx
134134 .collect (
135135 toMap (e -> e .getKey (), e -> e .getValue (), (e1 , e2 ) -> e2 ,
136136 LinkedHashMap ::new ));
137-
137+
138138 int i = 0 ;
139- for (String key : sorted .keySet ()) {
139+ for (String key : sorted .keySet ()) {
140140 if (i >0 ) {
141141 doubleSpendSet .add (key );
142142 }
143143 i ++;
144144 }
145145 }
146146
147+ private boolean isAllOutsWithSingleIns (Set <String > vals ) {
148+ // If all the subs have only one 'up', as following, the up MUST have been spent.
149+ // *
150+ // / \
151+ // * *
152+ for (String s : vals ) {
153+ Set <String > set = inGraph .get (s );
154+ if (set .size () != 1 ) {
155+ return false ;
156+ }
157+ }
158+ return true ;
159+ }
160+
161+ private boolean isAllOutsOkWithMultipleIns (String key , Set <String > vals ) {
162+ // *1 *2
163+ // / \ /
164+ // *3 *4
165+ // If *2 is doubleSpent, *4 will be doubleSpent too. so *1 should be countted in total balance install of *3.
166+
167+ // divide all the vals into groups by the transaction hash.
168+ Map <String , Set <String >> groups = new HashMap <>();
169+ for (String s : vals ) {
170+ String [] out = s .split (":" );
171+ String hash = out [0 ];
172+ if (!groups .containsKey (hash )) {
173+ Set <String > set = new HashSet <>();
174+ set .add (s );
175+ groups .put (hash , set );
176+ } else {
177+ Set <String > set = groups .get (hash );
178+ set .add (s );
179+ }
180+ }
181+
182+ // check each group if it have an doubleSpent item
183+ for (String k : groups .keySet ()) {
184+ boolean allTxnOutOk = true ;
185+ for (String s : groups .get (k )) {
186+ if (isDoubleSpend (s )) {
187+ allTxnOutOk = false ;
188+ }
189+ }
190+
191+ if (allTxnOutOk ) {
192+ return true ;
193+ }
194+ }
195+
196+ return false ;
197+ }
198+
147199 public Boolean isSpent (String key ) {
148- return outGraph .containsKey (key );
200+ if (outGraph .containsKey (key )) {
201+ Set <String > vals = outGraph .get (key );
202+
203+ if (isAllOutsWithSingleIns (vals )) {
204+ return true ;
205+ }
206+
207+ if (isAllOutsOkWithMultipleIns (key , vals )) {
208+ return true ;
209+ }
210+ }
211+
212+ return false ;
149213 }
150214
151215 public Boolean isDoubleSpend (String key ) {
@@ -196,7 +260,7 @@ public void printGraph(Map<String, Set<String>> graph, String k, Set<String> spe
196260 if (spend .contains (val )) {
197261 writer .write ("\" " +IotaUtils .abbrieviateHash (val , 6 )+"\" [" + "shape=square]\n " );
198262 }
199- }
263+ }
200264 } else {
201265 System .out .println ("\" " + IotaUtils .abbrieviateHash (key , 6 ) + "\" ->" +
202266 "\" " + IotaUtils .abbrieviateHash (val , 6 ) + "\" " );
@@ -205,8 +269,8 @@ public void printGraph(Map<String, Set<String>> graph, String k, Set<String> spe
205269 System .out .println ("\" " +IotaUtils .abbrieviateHash (val , 6 )+"\" [" + "style=filled, fillcolor=red]" );
206270 } else if (!isSpent (val )) {
207271 System .out .println ("\" " +IotaUtils .abbrieviateHash (val , 6 )+"\" [" + "style=filled, fillcolor=green]" );
208- }
209- }
272+ }
273+ }
210274 } catch (Exception e ) {
211275 ;
212276 }
0 commit comments