Skip to content

Commit 3ea19f3

Browse files
author
Srinivasan Muralidharan
committed
FAB-1281 add escc, vscc, policy to lccc
https://jira.hyperledger.org/browse/FAB-1281 In addition to name and deployment spec, escc, vscc and policy needs to be set on the chaincode at deployment time. This also removes use of the Table structure to basic GetState PutState to store a chaincode. A go structure is defined for it and serialized using proto. Note that "chainid" is not stored. The lccc is likely instantiated on each chain's ledger and the chain context is clear. The chain is still passed as params in the functions (ie, no change there) in case its needed for chain specific accesses. Change-Id: Idef7de7381f3a5552dc9acd80c203599a7f9c544 Signed-off-by: Srinivasan Muralidharan <[email protected]>
1 parent da16559 commit 3ea19f3

File tree

2 files changed

+55
-79
lines changed

2 files changed

+55
-79
lines changed

core/chaincode/lccc.go

+54-78
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,21 @@ import (
3030
"golang.org/x/net/context"
3131
)
3232

33+
//define the datastructure for chaincodes to be serialized by proto
34+
type chaincodeData struct {
35+
name string `protobuf:"bytes,1,opt,name=name"`
36+
version int32 `protobuf:"bytes,2,opt,name=version,proto3"`
37+
depSpec []byte `protobuf:"bytes,3,opt,name=depSpec,proto3"`
38+
escc string `protobuf:"bytes,4,opt,name=escc"`
39+
vscc string `protobuf:"bytes,5,opt,name=vscc"`
40+
policy []byte `protobuf:"bytes,6,opt,name=policy"`
41+
}
42+
43+
//implement functions needed from proto.Message for proto's mar/unmarshal functions
44+
func (cd *chaincodeData) Reset() { *cd = chaincodeData{} }
45+
func (cd *chaincodeData) String() string { return proto.CompactTextString(cd) }
46+
func (*chaincodeData) ProtoMessage() {}
47+
3348
//The life cycle system chaincode manages chaincodes deployed
3449
//on this peer. It manages chaincodes via Invoke proposals.
3550
// "Args":["deploy",<ChaincodeDeploymentSpec>]
@@ -115,10 +130,10 @@ func (f InvalidDeploymentSpecErr) Error() string {
115130
return fmt.Sprintf("Invalid deployment spec : %s", string(f))
116131
}
117132

118-
//ChaincodeExistsErr chaincode exists error
119-
type ChaincodeExistsErr string
133+
//ExistsErr chaincode exists error
134+
type ExistsErr string
120135

121-
func (t ChaincodeExistsErr) Error() string {
136+
func (t ExistsErr) Error() string {
122137
return fmt.Sprintf("Chaincode exists %s", string(t))
123138
}
124139

@@ -136,79 +151,49 @@ func (f InvalidChaincodeNameErr) Error() string {
136151
return fmt.Sprintf("invalid chain code name %s", string(f))
137152
}
138153

139-
//-------------- helper functions ------------------
140-
//create the table to maintain list of chaincodes maintained in this
141-
//blockchain.
142-
func (lccc *LifeCycleSysCC) createChaincodeTable(stub shim.ChaincodeStubInterface, cctable string) error {
143-
// Create table one
144-
var colDefs []*shim.ColumnDefinition
145-
nameColDef := shim.ColumnDefinition{Name: "name",
146-
Type: shim.ColumnDefinition_STRING, Key: true}
147-
versColDef := shim.ColumnDefinition{Name: "version",
148-
Type: shim.ColumnDefinition_INT32, Key: false}
149-
150-
//QUESTION - Should code be separately maintained ?
151-
codeDef := shim.ColumnDefinition{Name: "code",
152-
Type: shim.ColumnDefinition_BYTES, Key: false}
153-
colDefs = append(colDefs, &nameColDef)
154-
colDefs = append(colDefs, &versColDef)
155-
colDefs = append(colDefs, &codeDef)
156-
return stub.CreateTable(cctable, colDefs)
157-
}
158-
159-
//register create the chaincode table. name can be used to different
160-
//tables of chaincodes. This would provide the way to associate chaincodes
161-
//with chains(and ledgers)
162-
func (lccc *LifeCycleSysCC) register(stub shim.ChaincodeStubInterface, name string) error {
163-
ccname := CHAINCODETABLE + "-" + name
154+
//MarshallErr error marshaling/unmarshalling
155+
type MarshallErr string
164156

165-
row, err := stub.GetTable(ccname)
166-
if err == nil && row != nil { //table exists, do nothing
167-
return AlreadyRegisteredErr(name)
168-
}
169-
170-
//there may be other err's but assume "not exists". Anything
171-
//more serious than that bound to show up
172-
err = lccc.createChaincodeTable(stub, ccname)
173-
174-
return err
157+
func (m MarshallErr) Error() string {
158+
return fmt.Sprintf("error while marshalling %s", string(m))
175159
}
176160

161+
//-------------- helper functions ------------------
177162
//create the chaincode on the given chain
178-
func (lccc *LifeCycleSysCC) createChaincode(stub shim.ChaincodeStubInterface, chainname string, ccname string, cccode []byte) (*shim.Row, error) {
179-
var columns []*shim.Column
163+
func (lccc *LifeCycleSysCC) createChaincode(stub shim.ChaincodeStubInterface, chainname string, ccname string, cccode []byte) (*chaincodeData, error) {
164+
cd := &chaincodeData{name: ccname, depSpec: cccode}
165+
cdbytes, err := proto.Marshal(cd)
166+
if err != nil {
167+
return nil, err
168+
}
180169

181-
nameCol := shim.Column{Value: &shim.Column_String_{String_: ccname}}
182-
versCol := shim.Column{Value: &shim.Column_Int32{Int32: 0}}
183-
codeCol := shim.Column{Value: &shim.Column_Bytes{Bytes: cccode}}
170+
if cdbytes == nil {
171+
return nil, MarshallErr(ccname)
172+
}
184173

185-
columns = append(columns, &nameCol)
186-
columns = append(columns, &versCol)
187-
columns = append(columns, &codeCol)
174+
err = stub.PutState(ccname, cdbytes)
188175

189-
row := &shim.Row{Columns: columns}
190-
_, err := stub.InsertRow(CHAINCODETABLE+"-"+chainname, *row)
191-
if err != nil {
192-
return nil, fmt.Errorf("insertion of chaincode failed. %s", err)
193-
}
194-
return row, nil
176+
return cd, err
195177
}
196178

197179
//checks for existence of chaincode on the given chain
198-
func (lccc *LifeCycleSysCC) getChaincode(stub shim.ChaincodeStubInterface, chainname string, ccname string) (shim.Row, bool, error) {
199-
var columns []shim.Column
200-
nameCol := shim.Column{Value: &shim.Column_String_{String_: ccname}}
201-
columns = append(columns, nameCol)
202-
203-
row, err := stub.GetRow(CHAINCODETABLE+"-"+chainname, columns)
180+
func (lccc *LifeCycleSysCC) getChaincode(stub shim.ChaincodeStubInterface, chainname string, ccname string) (*chaincodeData, error) {
181+
cdbytes, err := stub.GetState(ccname)
204182
if err != nil {
205-
return shim.Row{}, false, err
183+
return nil, err
206184
}
207185

208-
if len(row.Columns) > 0 {
209-
return row, true, nil
186+
if cdbytes != nil {
187+
cd := &chaincodeData{}
188+
err = proto.Unmarshal(cdbytes, cd)
189+
if err != nil {
190+
return nil, MarshallErr(ccname)
191+
}
192+
193+
return cd, nil
210194
}
211-
return row, false, nil
195+
196+
return nil, nil
212197
}
213198

214199
//getChaincodeDeploymentSpec returns a ChaincodeDeploymentSpec given args
@@ -302,15 +287,6 @@ func (lccc *LifeCycleSysCC) deploy(stub shim.ChaincodeStubInterface, chainname s
302287

303288
//this implements "deploy" Invoke transaction
304289
func (lccc *LifeCycleSysCC) executeDeploy(stub shim.ChaincodeStubInterface, chainname string, code []byte) error {
305-
//lazy creation of chaincode table for chainname...its possible
306-
//there are chains without chaincodes
307-
if err := lccc.register(stub, chainname); err != nil {
308-
//if its already registered, ok... proceed
309-
if _, ok := err.(AlreadyRegisteredErr); !ok {
310-
return err
311-
}
312-
}
313-
314290
cds, err := lccc.getChaincodeDeploymentSpec(code)
315291

316292
if err != nil {
@@ -325,9 +301,9 @@ func (lccc *LifeCycleSysCC) executeDeploy(stub shim.ChaincodeStubInterface, chai
325301
return err
326302
}
327303

328-
_, exists, err := lccc.getChaincode(stub, chainname, cds.ChaincodeSpec.ChaincodeID.Name)
329-
if exists {
330-
return ChaincodeExistsErr(cds.ChaincodeSpec.ChaincodeID.Name)
304+
cd, err := lccc.getChaincode(stub, chainname, cds.ChaincodeSpec.ChaincodeID.Name)
305+
if cd != nil {
306+
return ExistsErr(cds.ChaincodeSpec.ChaincodeID.Name)
331307
}
332308

333309
/**TODO - this is done in the endorser service for now so we can
@@ -392,16 +368,16 @@ func (lccc *LifeCycleSysCC) Invoke(stub shim.ChaincodeStubInterface) ([]byte, er
392368
ccname := string(args[2])
393369
//get chaincode given <chain, name>
394370

395-
ccrow, exists, _ := lccc.getChaincode(stub, chain, ccname)
396-
if !exists {
371+
cd, _ := lccc.getChaincode(stub, chain, ccname)
372+
if cd == nil {
397373
logger.Debug("ChaincodeID [%s/%s] does not exist", chain, ccname)
398374
return nil, TXNotFoundErr(chain + "/" + ccname)
399375
}
400376

401377
if function == GETCCINFO {
402-
return []byte(ccrow.Columns[1].GetString_()), nil
378+
return []byte(cd.name), nil
403379
}
404-
return ccrow.Columns[2].GetBytes(), nil
380+
return cd.depSpec, nil
405381
}
406382

407383
return nil, InvalidFunctionErr(function)

core/chaincode/lccc_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ func TestRedeploy(t *testing.T) {
140140
//this should fail with exists error
141141
args = [][]byte{[]byte(DEPLOY), []byte("test"), b}
142142
_, err = stub.MockInvoke("1", args)
143-
if _, ok := err.(ChaincodeExistsErr); !ok {
143+
if _, ok := err.(ExistsErr); !ok {
144144
t.FailNow()
145145
}
146146
}

0 commit comments

Comments
 (0)