Skip to content

Commit

Permalink
[FABN-1130] Stop using "init" as default function name
Browse files Browse the repository at this point in the history
The SDK currently forces you to supply a function name
to the instantiate command; if you don't, it defaults
to "init". There is no need to specify a function name
during instantiate, and the new programming model does
not need you to call *any* function at instantiate time.

This is the v1.4 backport; in order to maintain compat
with existing SDK applications, this change will keep
the current behaviour if you don't pass "fcn", but will
change the behaviour if you pass "fcn" with a null or
empty string value (highly unlikely anyone is doing that).

Change-Id: Ia526d855f66fc428bca43786bc4555e9da074a41
Signed-off-by: Simon Stone <sstone1@uk.ibm.com>
  • Loading branch information
Simon Stone committed Feb 13, 2019
1 parent 433b5af commit 61a1eba
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 3 deletions.
8 changes: 6 additions & 2 deletions fabric-client/lib/Channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -2464,7 +2464,8 @@ const Channel = class {
* passed to the chaincode in the transientMap.
* @property {string} fcn - Optional. The function name to be returned when
* calling <code>stub.GetFunctionAndParameters()</code> in the target
* chaincode. Default is 'init'.
* chaincode. Default is 'init'; to pass in no function name, explicitly
* pass in fcn with a value of null or '' (empty string).
* @property {string[]} args - Optional. Array of string arguments to pass to
* the function identified by the <code>fcn</code> value.
* @property {Object} endorsement-policy - Optional. EndorsementPolicy object
Expand Down Expand Up @@ -2575,7 +2576,10 @@ const Channel = class {

// step 1: construct a ChaincodeSpec
const args = [];
args.push(Buffer.from(request.fcn ? request.fcn : 'init', 'utf8'));
const fcn = (typeof request.fcn === 'undefined' ? 'init' : request.fcn);
if (fcn) {
args.push(Buffer.from(fcn, 'utf8'));
}

for (const arg of request.args) {
args.push(Buffer.from(arg, 'utf8'));
Expand Down
175 changes: 174 additions & 1 deletion fabric-client/test/Channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -1227,7 +1227,180 @@ describe('Channel', () => {
});
});

describe('#_sendChaincodeProposal', () => {});
describe('#_sendChaincodeProposal', () => {

let mockPeers;
let txId;

beforeEach(() => {
mockPeers = [
sinon.createStubInstance(Peer),
sinon.createStubInstance(Peer)
];
sinon.stub(channel, '_getTargets').returns(mockPeers);
txId = client.newTransactionID();
});

it('should send an instantiate request with no function name (default to init) and no arguments', async () => {
const [, proposal] = await channel.sendInstantiateProposal({
chaincodeType: 'node',
chaincodeId: 'fabcar',
chaincodeVersion: '1.0.0',
txId
});
const payload = proposalProto.ChaincodeProposalPayload.decode(proposal.payload);
const input = proposalProto.ChaincodeInvocationSpec.decode(payload.input);
const args = input.chaincode_spec.input.args;
args.should.have.lengthOf(6);
const cds = proposalProto.ChaincodeDeploymentSpec.decode(args[2]);
cds.chaincode_spec.chaincode_id.name.should.equal('fabcar');
cds.chaincode_spec.chaincode_id.version.should.equal('1.0.0');
cds.chaincode_spec.input.args.should.have.lengthOf(1);
cds.chaincode_spec.input.args[0].toBuffer().toString().should.equal('init');
});

it('should send an instantiate request with no function name (explicit null) and no arguments', async () => {
const [, proposal] = await channel.sendInstantiateProposal({
chaincodeType: 'node',
chaincodeId: 'fabcar',
chaincodeVersion: '1.0.0',
fcn: null,
txId
});
const payload = proposalProto.ChaincodeProposalPayload.decode(proposal.payload);
const input = proposalProto.ChaincodeInvocationSpec.decode(payload.input);
const args = input.chaincode_spec.input.args;
args.should.have.lengthOf(6);
const cds = proposalProto.ChaincodeDeploymentSpec.decode(args[2]);
cds.chaincode_spec.chaincode_id.name.should.equal('fabcar');
cds.chaincode_spec.chaincode_id.version.should.equal('1.0.0');
cds.chaincode_spec.input.args.should.have.lengthOf(0);
});

it('should send an instantiate request with no function name (explicit empty string) and no arguments', async () => {
const [, proposal] = await channel.sendInstantiateProposal({
chaincodeType: 'node',
chaincodeId: 'fabcar',
chaincodeVersion: '1.0.0',
fcn: '',
txId
});
const payload = proposalProto.ChaincodeProposalPayload.decode(proposal.payload);
const input = proposalProto.ChaincodeInvocationSpec.decode(payload.input);
const args = input.chaincode_spec.input.args;
args.should.have.lengthOf(6);
const cds = proposalProto.ChaincodeDeploymentSpec.decode(args[2]);
cds.chaincode_spec.chaincode_id.name.should.equal('fabcar');
cds.chaincode_spec.chaincode_id.version.should.equal('1.0.0');
cds.chaincode_spec.input.args.should.have.lengthOf(0);
});

it('should send an instantiate request with a function name and no arguments', async () => {
const [, proposal] = await channel.sendInstantiateProposal({
chaincodeType: 'node',
chaincodeId: 'fabcar',
chaincodeVersion: '1.0.0',
fcn: 'initLedger',
txId
});
const payload = proposalProto.ChaincodeProposalPayload.decode(proposal.payload);
const input = proposalProto.ChaincodeInvocationSpec.decode(payload.input);
const args = input.chaincode_spec.input.args;
args.should.have.lengthOf(6);
const cds = proposalProto.ChaincodeDeploymentSpec.decode(args[2]);
cds.chaincode_spec.chaincode_id.name.should.equal('fabcar');
cds.chaincode_spec.chaincode_id.version.should.equal('1.0.0');
cds.chaincode_spec.input.args.should.have.lengthOf(1);
cds.chaincode_spec.input.args[0].toBuffer().toString().should.equal('initLedger');
});

it('should send an instantiate request with no function name (default to init) and some arguments', async () => {
const [, proposal] = await channel.sendInstantiateProposal({
chaincodeType: 'node',
chaincodeId: 'fabcar',
chaincodeVersion: '1.0.0',
args: ['hello', 'world'],
txId
});
const payload = proposalProto.ChaincodeProposalPayload.decode(proposal.payload);
const input = proposalProto.ChaincodeInvocationSpec.decode(payload.input);
const args = input.chaincode_spec.input.args;
args.should.have.lengthOf(6);
const cds = proposalProto.ChaincodeDeploymentSpec.decode(args[2]);
cds.chaincode_spec.chaincode_id.name.should.equal('fabcar');
cds.chaincode_spec.chaincode_id.version.should.equal('1.0.0');
cds.chaincode_spec.input.args.should.have.lengthOf(3);
cds.chaincode_spec.input.args[0].toBuffer().toString().should.equal('init');
cds.chaincode_spec.input.args[1].toBuffer().toString().should.equal('hello');
cds.chaincode_spec.input.args[2].toBuffer().toString().should.equal('world');
});

it('should send an instantiate request with no function name (explicit null) and some arguments', async () => {
const [, proposal] = await channel.sendInstantiateProposal({
chaincodeType: 'node',
chaincodeId: 'fabcar',
chaincodeVersion: '1.0.0',
fcn: null,
args: ['hello', 'world'],
txId
});
const payload = proposalProto.ChaincodeProposalPayload.decode(proposal.payload);
const input = proposalProto.ChaincodeInvocationSpec.decode(payload.input);
const args = input.chaincode_spec.input.args;
args.should.have.lengthOf(6);
const cds = proposalProto.ChaincodeDeploymentSpec.decode(args[2]);
cds.chaincode_spec.chaincode_id.name.should.equal('fabcar');
cds.chaincode_spec.chaincode_id.version.should.equal('1.0.0');
cds.chaincode_spec.input.args.should.have.lengthOf(2);
cds.chaincode_spec.input.args[0].toBuffer().toString().should.equal('hello');
cds.chaincode_spec.input.args[1].toBuffer().toString().should.equal('world');
});

it('should send an instantiate request with no function name (explicit empty string) and some arguments', async () => {
const [, proposal] = await channel.sendInstantiateProposal({
chaincodeType: 'node',
chaincodeId: 'fabcar',
chaincodeVersion: '1.0.0',
fcn: '',
args: ['hello', 'world'],
txId
});
const payload = proposalProto.ChaincodeProposalPayload.decode(proposal.payload);
const input = proposalProto.ChaincodeInvocationSpec.decode(payload.input);
const args = input.chaincode_spec.input.args;
args.should.have.lengthOf(6);
const cds = proposalProto.ChaincodeDeploymentSpec.decode(args[2]);
cds.chaincode_spec.chaincode_id.name.should.equal('fabcar');
cds.chaincode_spec.chaincode_id.version.should.equal('1.0.0');
cds.chaincode_spec.input.args.should.have.lengthOf(2);
cds.chaincode_spec.input.args[0].toBuffer().toString().should.equal('hello');
cds.chaincode_spec.input.args[1].toBuffer().toString().should.equal('world');
});

it('should send an instantiate request with a function name and some arguments', async () => {
const [, proposal] = await channel.sendInstantiateProposal({
chaincodeType: 'node',
chaincodeId: 'fabcar',
chaincodeVersion: '1.0.0',
fcn: 'initLedger',
args: ['hello', 'world'],
txId
});
const payload = proposalProto.ChaincodeProposalPayload.decode(proposal.payload);
const input = proposalProto.ChaincodeInvocationSpec.decode(payload.input);
const args = input.chaincode_spec.input.args;
args.should.have.lengthOf(6);
const cds = proposalProto.ChaincodeDeploymentSpec.decode(args[2]);
cds.chaincode_spec.chaincode_id.name.should.equal('fabcar');
cds.chaincode_spec.chaincode_id.version.should.equal('1.0.0');
cds.chaincode_spec.input.args.should.have.lengthOf(3);
cds.chaincode_spec.input.args[0].toBuffer().toString().should.equal('initLedger');
cds.chaincode_spec.input.args[1].toBuffer().toString().should.equal('hello');
cds.chaincode_spec.input.args[2].toBuffer().toString().should.equal('world');
});


});

describe('#sendTransactionProposal', () => {});

Expand Down
1 change: 1 addition & 0 deletions test/integration/memory.js
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ async function createChannel(t) {
chaincodePath: 'github.com/example_cc',
chaincodeId: 'example',
chaincodeVersion: 'v1',
fcn: 'init',
args: ['a', '100', 'b', '200'],
txId: tx_id
// targets is not required, however the logged in user may not have
Expand Down
1 change: 1 addition & 0 deletions test/integration/network-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ test('\n\n***** use the connection profile file *****\n\n', async (t) => {
request = {
chaincodeId: 'example',
chaincodeVersion: 'v1',
fcn: 'init',
args: ['a', '100', 'b', '200'],
txId: tx_id
// targets is not required, however the logged in user may not have
Expand Down
1 change: 1 addition & 0 deletions test/typescript/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ test('use the connection profile file', (t: any) => {
args: ['a', '100', 'b', '200'],
chaincodeId: 'examplets',
chaincodeVersion: 'v1',
fcn: 'init',
txId,
};

Expand Down
1 change: 1 addition & 0 deletions test/unit/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,7 @@ module.exports.setupChannel = async function(t, client_org1, client_org2, channe
chaincodePath: 'github.com/example_cc',
chaincodeId: 'example',
chaincodeVersion: 'v2',
fcn: 'init',
args: ['a', '100', 'b', '200'],
txId: tx_id,
targets: ['peer0.org1.example.com', 'peer0.org2.example.com'],
Expand Down

0 comments on commit 61a1eba

Please sign in to comment.