Skip to content

Commit 762a955

Browse files
[FAB-13800] Transaction Context
Change-Id: If4922e63a7324768f91e6963452098409e88ef2e Signed-off-by: gennady <[email protected]>
1 parent 351acb5 commit 762a955

File tree

4 files changed

+357
-0
lines changed

4 files changed

+357
-0
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
Copyright IBM Corp., DTCC All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package org.hyperledger.fabric.contract;
8+
9+
import org.hyperledger.fabric.shim.ChaincodeStub;
10+
11+
/**
12+
* Context provides {@link ChaincodeStub} API for handling world state
13+
*/
14+
public interface Context extends ChaincodeStub {
15+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
Copyright IBM Corp., DTCC All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package org.hyperledger.fabric.contract;
8+
9+
import org.hyperledger.fabric.shim.ChaincodeStub;
10+
11+
import java.lang.reflect.InvocationHandler;
12+
import java.lang.reflect.Method;
13+
import java.lang.reflect.Proxy;
14+
15+
/**
16+
* Factory to create {@link Context} from {@link ChaincodeStub}
17+
* by wrapping stub with dynamic proxy.
18+
*/
19+
public class ContextFactory {
20+
private static ContextFactory cf;
21+
22+
static synchronized public ContextFactory getInstance() {
23+
if (cf == null) {
24+
cf = new ContextFactory();
25+
}
26+
return cf;
27+
}
28+
29+
public synchronized Context createContext(final ChaincodeStub stub) {
30+
Context newContext = (Context) Proxy.newProxyInstance(
31+
this.getClass().getClassLoader(),
32+
new Class[]{Context.class},
33+
new ContextInvocationHandler(stub)
34+
);
35+
return newContext;
36+
}
37+
38+
static class ContextInvocationHandler implements InvocationHandler {
39+
40+
private ChaincodeStub stub;
41+
42+
ContextInvocationHandler(final ChaincodeStub stub) {
43+
this.stub = stub;
44+
}
45+
46+
@Override
47+
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
48+
Method m = stub.getClass().getMethod(method.getName(), method.getParameterTypes());
49+
return m.invoke(stub, args);
50+
}
51+
}
52+
53+
}
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
/*
2+
Copyright IBM Corp. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
package org.hyperledger.fabric.contract;
7+
8+
import com.google.protobuf.ByteString;
9+
import org.hyperledger.fabric.protos.peer.ChaincodeEventPackage;
10+
import org.hyperledger.fabric.protos.peer.ProposalPackage;
11+
import org.hyperledger.fabric.shim.Chaincode;
12+
import org.hyperledger.fabric.shim.ChaincodeStub;
13+
import org.hyperledger.fabric.shim.ledger.*;
14+
15+
import java.nio.charset.StandardCharsets;
16+
import java.time.Instant;
17+
import java.util.ArrayList;
18+
import java.util.HashMap;
19+
import java.util.List;
20+
import java.util.Map;
21+
import java.util.stream.Collectors;
22+
23+
public class ChaincodeStubNaiveImpl implements ChaincodeStub {
24+
private List<String> args;
25+
private List<byte[]> argsAsByte;
26+
private Map<String, ByteString> state;
27+
private Chaincode.Response resp;
28+
29+
ChaincodeStubNaiveImpl() {
30+
args = new ArrayList<>();
31+
args.add("func1");
32+
args.add("param1");
33+
args.add("param2");
34+
35+
state = new HashMap<>();
36+
state.put("a", ByteString.copyFrom("asdf", StandardCharsets.UTF_8));
37+
38+
argsAsByte = null;
39+
40+
resp = new Chaincode.Response(404, "Wrong cc name", new byte[]{});
41+
}
42+
43+
@Override
44+
public List<byte[]> getArgs() {
45+
if (argsAsByte == null) {
46+
argsAsByte = args.stream().map(i -> i.getBytes()).collect(Collectors.toList());
47+
}
48+
return argsAsByte;
49+
}
50+
51+
@Override
52+
public List<String> getStringArgs() {
53+
return args;
54+
}
55+
56+
@Override
57+
public String getFunction() {
58+
return args.get(0);
59+
}
60+
61+
@Override
62+
public List<String> getParameters() {
63+
return args.subList(1, args.size());
64+
}
65+
66+
@Override
67+
public String getTxId() {
68+
return "tx0";
69+
}
70+
71+
@Override
72+
public String getChannelId() {
73+
return "ch0";
74+
}
75+
76+
@Override
77+
public Chaincode.Response invokeChaincode(String chaincodeName, List<byte[]> args, String channel) {
78+
return resp;
79+
}
80+
81+
@Override
82+
public byte[] getState(String key) {
83+
return state.get(key).toByteArray();
84+
}
85+
86+
@Override
87+
public byte[] getStateValidationParameter(String key) {
88+
return new byte[0];
89+
}
90+
91+
@Override
92+
public void putState(String key, byte[] value) {
93+
state.put(key, ByteString.copyFrom(value));
94+
95+
}
96+
97+
@Override
98+
public void setStateValidationParameter(String key, byte[] value) {
99+
100+
}
101+
102+
@Override
103+
public void delState(String key) {
104+
state.remove(key);
105+
}
106+
107+
@Override
108+
public QueryResultsIterator<KeyValue> getStateByRange(String startKey, String endKey) {
109+
return null;
110+
}
111+
112+
@Override
113+
public QueryResultsIteratorWithMetadata<KeyValue> getStateByRangeWithPagination(String startKey, String endKey, int pageSize, String bookmark) {
114+
return null;
115+
}
116+
117+
@Override
118+
public QueryResultsIterator<KeyValue> getStateByPartialCompositeKey(String compositeKey) {
119+
return null;
120+
}
121+
122+
@Override
123+
public QueryResultsIterator<KeyValue> getStateByPartialCompositeKey(String objectType, String... attributes) {
124+
return null;
125+
}
126+
127+
@Override
128+
public QueryResultsIterator<KeyValue> getStateByPartialCompositeKey(CompositeKey compositeKey) {
129+
return null;
130+
}
131+
132+
@Override
133+
public QueryResultsIteratorWithMetadata<KeyValue> getStateByPartialCompositeKeyWithPagination(CompositeKey compositeKey, int pageSize, String bookmark) {
134+
return null;
135+
}
136+
137+
@Override
138+
public CompositeKey createCompositeKey(String objectType, String... attributes) {
139+
return null;
140+
}
141+
142+
@Override
143+
public CompositeKey splitCompositeKey(String compositeKey) {
144+
return null;
145+
}
146+
147+
@Override
148+
public QueryResultsIterator<KeyValue> getQueryResult(String query) {
149+
return null;
150+
}
151+
152+
@Override
153+
public QueryResultsIteratorWithMetadata<KeyValue> getQueryResultWithPagination(String query, int pageSize, String bookmark) {
154+
return null;
155+
}
156+
157+
@Override
158+
public QueryResultsIterator<KeyModification> getHistoryForKey(String key) {
159+
return null;
160+
}
161+
162+
@Override
163+
public byte[] getPrivateData(String collection, String key) {
164+
return new byte[0];
165+
}
166+
167+
@Override
168+
public byte[] getPrivateDataValidationParameter(String collection, String key) {
169+
return new byte[0];
170+
}
171+
172+
@Override
173+
public void putPrivateData(String collection, String key, byte[] value) {
174+
175+
}
176+
177+
@Override
178+
public void setPrivateDataValidationParameter(String collection, String key, byte[] value) {
179+
180+
}
181+
182+
@Override
183+
public void delPrivateData(String collection, String key) {
184+
185+
}
186+
187+
@Override
188+
public QueryResultsIterator<KeyValue> getPrivateDataByRange(String collection, String startKey, String endKey) {
189+
return null;
190+
}
191+
192+
@Override
193+
public QueryResultsIterator<KeyValue> getPrivateDataByPartialCompositeKey(String collection, String compositeKey) {
194+
return null;
195+
}
196+
197+
@Override
198+
public QueryResultsIterator<KeyValue> getPrivateDataByPartialCompositeKey(String collection, CompositeKey compositeKey) {
199+
return null;
200+
}
201+
202+
@Override
203+
public QueryResultsIterator<KeyValue> getPrivateDataByPartialCompositeKey(String collection, String objectType, String... attributes) {
204+
return null;
205+
}
206+
207+
@Override
208+
public QueryResultsIterator<KeyValue> getPrivateDataQueryResult(String collection, String query) {
209+
return null;
210+
}
211+
212+
@Override
213+
public void setEvent(String name, byte[] payload) {
214+
215+
}
216+
217+
@Override
218+
public ChaincodeEventPackage.ChaincodeEvent getEvent() {
219+
return null;
220+
}
221+
222+
@Override
223+
public ProposalPackage.SignedProposal getSignedProposal() {
224+
return null;
225+
}
226+
227+
@Override
228+
public Instant getTxTimestamp() {
229+
return null;
230+
}
231+
232+
@Override
233+
public byte[] getCreator() {
234+
return new byte[0];
235+
}
236+
237+
@Override
238+
public Map<String, byte[]> getTransient() {
239+
return null;
240+
}
241+
242+
@Override
243+
public byte[] getBinding() {
244+
return new byte[0];
245+
}
246+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
Copyright IBM Corp. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
package org.hyperledger.fabric.contract;
7+
8+
import org.hyperledger.fabric.shim.ChaincodeStub;
9+
import org.junit.Ignore;
10+
import org.junit.Test;
11+
12+
import java.util.Collections;
13+
14+
import static org.hamcrest.Matchers.*;
15+
import static org.junit.Assert.*;
16+
17+
public class ContextFactoryTest {
18+
19+
@Test
20+
public void getInstance() {
21+
ContextFactory f1 = ContextFactory.getInstance();
22+
ContextFactory f2 = ContextFactory.getInstance();
23+
assertThat(f1, sameInstance(f2));
24+
}
25+
26+
@Test
27+
public void createContext() {
28+
ChaincodeStub stub = new ChaincodeStubNaiveImpl();
29+
Context ctx = ContextFactory.getInstance().createContext(stub);
30+
31+
assertThat(stub.getArgs(), is(equalTo(ctx.getArgs())));
32+
assertThat(stub.getStringArgs(), is(equalTo(ctx.getStringArgs())));
33+
assertThat(stub.getFunction(), is(equalTo(ctx.getFunction())));
34+
assertThat(stub.getParameters(), is(equalTo(ctx.getParameters())));
35+
assertThat(stub.getTxId(), is(equalTo(ctx.getTxId())));
36+
assertThat(stub.getChannelId(), is(equalTo(ctx.getChannelId())));
37+
assertThat(stub.invokeChaincode("cc", Collections.emptyList(), "ch0"), is(equalTo(ctx.invokeChaincode("cc", Collections.emptyList(), "ch0"))));
38+
39+
assertThat(stub.getState("a"), is(equalTo(ctx.getState("a"))));
40+
ctx.putState("b", "sdfg".getBytes());
41+
assertThat(stub.getStringState("b"), is(equalTo(ctx.getStringState("b"))));
42+
}
43+
}

0 commit comments

Comments
 (0)