Skip to content

Commit

Permalink
[FAB-13800] Transaction Context
Browse files Browse the repository at this point in the history
Change-Id: If4922e63a7324768f91e6963452098409e88ef2e
Signed-off-by: gennady <[email protected]>
  • Loading branch information
gennadylaventman committed Mar 14, 2019
1 parent 351acb5 commit 762a955
Show file tree
Hide file tree
Showing 4 changed files with 357 additions and 0 deletions.
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 {
}
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);
}
}

}
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];
}
}
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"))));
}
}

0 comments on commit 762a955

Please sign in to comment.