3333import java .util .Map ;
3434import java .util .Set ;
3535
36+ import org .apache .commons .lang3 .tuple .Pair ;
37+
3638/**
3739 * A Go Checker for the detection of different cross-channel invocations in
3840 * Hyperledger Fabric.
3941 *
4042 * @author <a href="mailto:[email protected] ">Luca Olivieri</a> 4143 */
42- public class DifferentCrossChannelInvocationsChecker implements
44+ public class CrossChannelInvocationsIssuesChecker implements
4345 SemanticCheck <
4446 SimpleAbstractState <PointBasedHeap , ValueEnvironment <Tarsis >, TypeEnvironment <InferredTypes >>> {
4547
46- private Map <Statement , Set <Tarsis >> crossChannelInvocations ;
48+ private Map <Statement , Set <Tarsis >> crossContractInvocations ;
49+
50+ private boolean intraChaincode = true ;
4751
52+ public CrossChannelInvocationsIssuesChecker () {
53+ }
54+
55+ public CrossChannelInvocationsIssuesChecker (boolean intraChaincode ) {
56+ this .intraChaincode = intraChaincode ;
57+ }
4858 @ Override
4959 public void beforeExecution (CheckToolWithAnalysisResults <
5060 SimpleAbstractState <PointBasedHeap , ValueEnvironment <Tarsis >, TypeEnvironment <InferredTypes >>> tool ) {
51- crossChannelInvocations = new HashMap <>();
61+ crossContractInvocations = new HashMap <>();
5262 }
5363
5464 @ Override
5565 public void afterExecution (
5666 CheckToolWithAnalysisResults <
5767 SimpleAbstractState <PointBasedHeap , ValueEnvironment <Tarsis >,
5868 TypeEnvironment <InferredTypes >>> tool ) {
59-
60- Statement [] invocations = crossChannelInvocations .keySet ().toArray (new Statement [] {});
69+
70+ Set <Statement > singleCrossChannelInvocations = new HashSet <>();
71+
72+ //CASE 1: single CCIs with arbitrary channel
73+ Statement [] invocations = crossContractInvocations .keySet ().toArray (new Statement [] {});
74+ for (int i = 0 ; i < invocations .length ; i ++) {
75+ Set <Tarsis > stringApproximations = crossContractInvocations .get (invocations [i ]);
76+ for (Tarsis t : stringApproximations ) {
77+ if (mayCrossChannel (t )) {
78+ singleCrossChannelInvocations .add (invocations [i ]);
79+ break ;
80+ }
81+ }
82+ }
83+
84+ for (Statement cch : singleCrossChannelInvocations ) {
85+ tool .warnOn (cch , "Detected possible cross-channel invocation. It may lead to a lack of transparency because no new transactions are created during the invocation." );
86+ if (intraChaincode )
87+ tool .warnOn (cch , "Detected possible cross-channel invocation. It may lead to uncommited write operations during the execution of callee chaincode." );
88+ }
89+
90+ //CASE 2: CCIs with different channels
91+ Set <Pair <Statement ,Statement >> multipleCrossChannelInvocations = new HashSet <>();
92+
6193 boolean isDiff = false ;
6294 for (int i = 0 ; i < invocations .length - 1 ; i ++) {
6395 for (int j = i + 1 ; j < invocations .length ; j ++) {
64- Set <Tarsis > t1Set = crossChannelInvocations .get (invocations [i ]);
65- Set <Tarsis > t2Set = crossChannelInvocations .get (invocations [j ]);
96+ Set <Tarsis > t1Set = crossContractInvocations .get (invocations [i ]);
97+ Set <Tarsis > t2Set = crossContractInvocations .get (invocations [j ]);
6698 for (Tarsis t1 : t1Set ) {
6799 for (Tarsis t2 : t2Set ) {
68100 if (t1 .isTop () || t2 .isTop ()
@@ -79,13 +111,30 @@ public void afterExecution(
79111 break ;
80112 }
81113
82- if (isDiff )
83- tool .warnOn (invocations [i ],
84- "Detected cross-channel invocations on different channels. The other invocation: "
85- + invocations [j ].getLocation ());
114+ if (isDiff ) {
115+ if (!multipleCrossChannelInvocations .contains (Pair .of (invocations [j ], invocations [i ])))
116+ multipleCrossChannelInvocations .add (Pair .of (invocations [i ], invocations [j ]));
117+ }
118+
86119 }
87120 }
121+
122+ for ( Pair <Statement , Statement > cchs : multipleCrossChannelInvocations ) {
123+ tool .warnOn (cchs .getLeft (),
124+ "Detected cross-channel invocations on different channels. The other invocation: "
125+ + cchs .getRight ().getLocation () + ". They may lead to a lack of transparency because no new transactions are created during the invocation." );
126+ if (intraChaincode )
127+ tool .warnOn (cchs .getLeft (),
128+ "Detected cross-channel invocations on different channels. The other invocation: "
129+ + cchs .getRight ().getLocation () + ". They may lead to uncommited write operations during the execution of callee chaincode." );
130+ }
131+
132+ }
88133
134+ private boolean mayCrossChannel (Tarsis t ) {
135+ return t .isTop () || t .getAutomaton ().getFinalStates ().size () > 2
136+ || AutomatonUtils .containsTopTransaction (t .getAutomaton ())
137+ || AutomatonUtils .hasCycle (t .getAutomaton ());
89138 }
90139
91140 @ Override
@@ -142,9 +191,9 @@ public boolean visit(
142191 channelValues = extractChannelValues (call , call .getParameters ().length , node , result );
143192 }
144193
145- crossChannelInvocations .putIfAbsent (call , new HashSet <>());
194+ crossContractInvocations .putIfAbsent (call , new HashSet <>());
146195 if (channelValues != null )
147- crossChannelInvocations .get (call ).addAll (channelValues );
196+ crossContractInvocations .get (call ).addAll (channelValues );
148197 }
149198
150199 } catch (SemanticException e ) {
0 commit comments