-
Notifications
You must be signed in to change notification settings - Fork 207
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Change-Id: If4922e63a7324768f91e6963452098409e88ef2e Signed-off-by: gennady <[email protected]>
- Loading branch information
1 parent
351acb5
commit 762a955
Showing
4 changed files
with
357 additions
and
0 deletions.
There are no files selected for viewing
15 changes: 15 additions & 0 deletions
15
fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/Context.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/* | ||
Copyright IBM Corp., DTCC All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package org.hyperledger.fabric.contract; | ||
|
||
import org.hyperledger.fabric.shim.ChaincodeStub; | ||
|
||
/** | ||
* Context provides {@link ChaincodeStub} API for handling world state | ||
*/ | ||
public interface Context extends ChaincodeStub { | ||
} |
53 changes: 53 additions & 0 deletions
53
fabric-chaincode-shim/src/main/java/org/hyperledger/fabric/contract/ContextFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/* | ||
Copyright IBM Corp., DTCC All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package org.hyperledger.fabric.contract; | ||
|
||
import org.hyperledger.fabric.shim.ChaincodeStub; | ||
|
||
import java.lang.reflect.InvocationHandler; | ||
import java.lang.reflect.Method; | ||
import java.lang.reflect.Proxy; | ||
|
||
/** | ||
* Factory to create {@link Context} from {@link ChaincodeStub} | ||
* by wrapping stub with dynamic proxy. | ||
*/ | ||
public class ContextFactory { | ||
private static ContextFactory cf; | ||
|
||
static synchronized public ContextFactory getInstance() { | ||
if (cf == null) { | ||
cf = new ContextFactory(); | ||
} | ||
return cf; | ||
} | ||
|
||
public synchronized Context createContext(final ChaincodeStub stub) { | ||
Context newContext = (Context) Proxy.newProxyInstance( | ||
this.getClass().getClassLoader(), | ||
new Class[]{Context.class}, | ||
new ContextInvocationHandler(stub) | ||
); | ||
return newContext; | ||
} | ||
|
||
static class ContextInvocationHandler implements InvocationHandler { | ||
|
||
private ChaincodeStub stub; | ||
|
||
ContextInvocationHandler(final ChaincodeStub stub) { | ||
this.stub = stub; | ||
} | ||
|
||
@Override | ||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { | ||
Method m = stub.getClass().getMethod(method.getName(), method.getParameterTypes()); | ||
return m.invoke(stub, args); | ||
} | ||
} | ||
|
||
} |
246 changes: 246 additions & 0 deletions
246
...-chaincode-shim/src/test/java/org/hyperledger/fabric/contract/ChaincodeStubNaiveImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,246 @@ | ||
/* | ||
Copyright IBM Corp. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
package org.hyperledger.fabric.contract; | ||
|
||
import com.google.protobuf.ByteString; | ||
import org.hyperledger.fabric.protos.peer.ChaincodeEventPackage; | ||
import org.hyperledger.fabric.protos.peer.ProposalPackage; | ||
import org.hyperledger.fabric.shim.Chaincode; | ||
import org.hyperledger.fabric.shim.ChaincodeStub; | ||
import org.hyperledger.fabric.shim.ledger.*; | ||
|
||
import java.nio.charset.StandardCharsets; | ||
import java.time.Instant; | ||
import java.util.ArrayList; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.stream.Collectors; | ||
|
||
public class ChaincodeStubNaiveImpl implements ChaincodeStub { | ||
private List<String> args; | ||
private List<byte[]> argsAsByte; | ||
private Map<String, ByteString> state; | ||
private Chaincode.Response resp; | ||
|
||
ChaincodeStubNaiveImpl() { | ||
args = new ArrayList<>(); | ||
args.add("func1"); | ||
args.add("param1"); | ||
args.add("param2"); | ||
|
||
state = new HashMap<>(); | ||
state.put("a", ByteString.copyFrom("asdf", StandardCharsets.UTF_8)); | ||
|
||
argsAsByte = null; | ||
|
||
resp = new Chaincode.Response(404, "Wrong cc name", new byte[]{}); | ||
} | ||
|
||
@Override | ||
public List<byte[]> getArgs() { | ||
if (argsAsByte == null) { | ||
argsAsByte = args.stream().map(i -> i.getBytes()).collect(Collectors.toList()); | ||
} | ||
return argsAsByte; | ||
} | ||
|
||
@Override | ||
public List<String> getStringArgs() { | ||
return args; | ||
} | ||
|
||
@Override | ||
public String getFunction() { | ||
return args.get(0); | ||
} | ||
|
||
@Override | ||
public List<String> getParameters() { | ||
return args.subList(1, args.size()); | ||
} | ||
|
||
@Override | ||
public String getTxId() { | ||
return "tx0"; | ||
} | ||
|
||
@Override | ||
public String getChannelId() { | ||
return "ch0"; | ||
} | ||
|
||
@Override | ||
public Chaincode.Response invokeChaincode(String chaincodeName, List<byte[]> args, String channel) { | ||
return resp; | ||
} | ||
|
||
@Override | ||
public byte[] getState(String key) { | ||
return state.get(key).toByteArray(); | ||
} | ||
|
||
@Override | ||
public byte[] getStateValidationParameter(String key) { | ||
return new byte[0]; | ||
} | ||
|
||
@Override | ||
public void putState(String key, byte[] value) { | ||
state.put(key, ByteString.copyFrom(value)); | ||
|
||
} | ||
|
||
@Override | ||
public void setStateValidationParameter(String key, byte[] value) { | ||
|
||
} | ||
|
||
@Override | ||
public void delState(String key) { | ||
state.remove(key); | ||
} | ||
|
||
@Override | ||
public QueryResultsIterator<KeyValue> getStateByRange(String startKey, String endKey) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public QueryResultsIteratorWithMetadata<KeyValue> getStateByRangeWithPagination(String startKey, String endKey, int pageSize, String bookmark) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public QueryResultsIterator<KeyValue> getStateByPartialCompositeKey(String compositeKey) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public QueryResultsIterator<KeyValue> getStateByPartialCompositeKey(String objectType, String... attributes) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public QueryResultsIterator<KeyValue> getStateByPartialCompositeKey(CompositeKey compositeKey) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public QueryResultsIteratorWithMetadata<KeyValue> getStateByPartialCompositeKeyWithPagination(CompositeKey compositeKey, int pageSize, String bookmark) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public CompositeKey createCompositeKey(String objectType, String... attributes) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public CompositeKey splitCompositeKey(String compositeKey) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public QueryResultsIterator<KeyValue> getQueryResult(String query) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public QueryResultsIteratorWithMetadata<KeyValue> getQueryResultWithPagination(String query, int pageSize, String bookmark) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public QueryResultsIterator<KeyModification> getHistoryForKey(String key) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public byte[] getPrivateData(String collection, String key) { | ||
return new byte[0]; | ||
} | ||
|
||
@Override | ||
public byte[] getPrivateDataValidationParameter(String collection, String key) { | ||
return new byte[0]; | ||
} | ||
|
||
@Override | ||
public void putPrivateData(String collection, String key, byte[] value) { | ||
|
||
} | ||
|
||
@Override | ||
public void setPrivateDataValidationParameter(String collection, String key, byte[] value) { | ||
|
||
} | ||
|
||
@Override | ||
public void delPrivateData(String collection, String key) { | ||
|
||
} | ||
|
||
@Override | ||
public QueryResultsIterator<KeyValue> getPrivateDataByRange(String collection, String startKey, String endKey) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public QueryResultsIterator<KeyValue> getPrivateDataByPartialCompositeKey(String collection, String compositeKey) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public QueryResultsIterator<KeyValue> getPrivateDataByPartialCompositeKey(String collection, CompositeKey compositeKey) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public QueryResultsIterator<KeyValue> getPrivateDataByPartialCompositeKey(String collection, String objectType, String... attributes) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public QueryResultsIterator<KeyValue> getPrivateDataQueryResult(String collection, String query) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public void setEvent(String name, byte[] payload) { | ||
|
||
} | ||
|
||
@Override | ||
public ChaincodeEventPackage.ChaincodeEvent getEvent() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public ProposalPackage.SignedProposal getSignedProposal() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public Instant getTxTimestamp() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public byte[] getCreator() { | ||
return new byte[0]; | ||
} | ||
|
||
@Override | ||
public Map<String, byte[]> getTransient() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public byte[] getBinding() { | ||
return new byte[0]; | ||
} | ||
} |
43 changes: 43 additions & 0 deletions
43
fabric-chaincode-shim/src/test/java/org/hyperledger/fabric/contract/ContextFactoryTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/* | ||
Copyright IBM Corp. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
package org.hyperledger.fabric.contract; | ||
|
||
import org.hyperledger.fabric.shim.ChaincodeStub; | ||
import org.junit.Ignore; | ||
import org.junit.Test; | ||
|
||
import java.util.Collections; | ||
|
||
import static org.hamcrest.Matchers.*; | ||
import static org.junit.Assert.*; | ||
|
||
public class ContextFactoryTest { | ||
|
||
@Test | ||
public void getInstance() { | ||
ContextFactory f1 = ContextFactory.getInstance(); | ||
ContextFactory f2 = ContextFactory.getInstance(); | ||
assertThat(f1, sameInstance(f2)); | ||
} | ||
|
||
@Test | ||
public void createContext() { | ||
ChaincodeStub stub = new ChaincodeStubNaiveImpl(); | ||
Context ctx = ContextFactory.getInstance().createContext(stub); | ||
|
||
assertThat(stub.getArgs(), is(equalTo(ctx.getArgs()))); | ||
assertThat(stub.getStringArgs(), is(equalTo(ctx.getStringArgs()))); | ||
assertThat(stub.getFunction(), is(equalTo(ctx.getFunction()))); | ||
assertThat(stub.getParameters(), is(equalTo(ctx.getParameters()))); | ||
assertThat(stub.getTxId(), is(equalTo(ctx.getTxId()))); | ||
assertThat(stub.getChannelId(), is(equalTo(ctx.getChannelId()))); | ||
assertThat(stub.invokeChaincode("cc", Collections.emptyList(), "ch0"), is(equalTo(ctx.invokeChaincode("cc", Collections.emptyList(), "ch0")))); | ||
|
||
assertThat(stub.getState("a"), is(equalTo(ctx.getState("a")))); | ||
ctx.putState("b", "sdfg".getBytes()); | ||
assertThat(stub.getStringState("b"), is(equalTo(ctx.getStringState("b")))); | ||
} | ||
} |