Skip to content

Commit 3f2cb2c

Browse files
committed
FAB-514 Default endorser,validator system chaincodes
For now, these scc are no-ops, are used to check the interfaces between endorsers and committers for the end-to-end skeleton. Over time, we will add signature and actual validation of blocks Handles JIRA issue https://jira.hyperledger.org/browse/FAB-514 (patch 3 redid goimports for importsysccs) Change-Id: I7a35ed87f83c82f14b1675b955ed5521e7fbda70 Signed-off-by: tuand27613 <[email protected]>
1 parent 03c4a70 commit 3f2cb2c

6 files changed

+315
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
Copyright IBM Corp. 2016 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package escc
18+
19+
import (
20+
"errors"
21+
22+
"github.com/hyperledger/fabric/core/chaincode/shim"
23+
//"github.com/hyperledger/fabric/core/crypto"
24+
)
25+
26+
// EndorserOneValidSignature implements the default endorsement policy, which is to
27+
// sign the proposal hash and the read-write set
28+
type EndorserOneValidSignature struct {
29+
}
30+
31+
// Init is called once when the chaincode started the first time
32+
func (e *EndorserOneValidSignature) Init(stub shim.ChaincodeStubInterface) ([]byte, error) {
33+
// best practice to do nothing (or very little) in Init
34+
return nil, nil
35+
}
36+
37+
// Invoke is called to endorse the specified Proposal
38+
// For now, we sign the input and return the endorsed result. Later we can expand
39+
// the chaincode to provide more sophisticate policy processing such as enabling
40+
// policy specification to be coded as a transaction of the chaincode and Client
41+
// could select which policy to use for endorsement using parameter
42+
// @return signature of Action object or error
43+
// Note that Peer calls this function with 3 arguments, where args[0] is the
44+
// function name and args[1] is the Action object and args[2] is Proposal object
45+
func (e *EndorserOneValidSignature) Invoke(stub shim.ChaincodeStubInterface) ([]byte, error) {
46+
// args[0] - function name (not used now)
47+
// args[1] - serialized Action object
48+
// args[2] - serialized Proposal object (not used)
49+
args := stub.GetArgs()
50+
if len(args) < 3 {
51+
return nil, errors.New("Incorrect number of arguments")
52+
}
53+
54+
if args[1] == nil {
55+
return nil, errors.New("Action object is null")
56+
}
57+
58+
// TODO: since we are just trying to get the end-to-end happy path going, we return a fake signed proposal
59+
// Once the scc interface is updated to have a pointer to the peer SecHelper, we will compute the actual signature
60+
return []byte("true"), nil
61+
//return crypto.sign(args[1])
62+
}
63+
64+
// Query is here to satisfy the Chaincode interface. We don't need it for this system chaincode
65+
func (e *EndorserOneValidSignature) Query(stub shim.ChaincodeStubInterface) ([]byte, error) {
66+
return nil, nil
67+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
Copyright IBM Corp. 2016 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
package escc
17+
18+
import (
19+
"fmt"
20+
"testing"
21+
22+
"github.com/golang/protobuf/proto"
23+
"github.com/hyperledger/fabric/core/chaincode/shim"
24+
pb "github.com/hyperledger/fabric/protos"
25+
)
26+
27+
func TestInit(t *testing.T) {
28+
e := new(EndorserOneValidSignature)
29+
stub := shim.NewMockStub("endorseronevalidsignature", e)
30+
31+
if _, err := stub.MockInit("1", nil); err != nil {
32+
fmt.Println("Init failed", err)
33+
t.FailNow()
34+
}
35+
}
36+
37+
func TestInvoke(t *testing.T) {
38+
e := new(EndorserOneValidSignature)
39+
stub := shim.NewMockStub("endorseronevalidsignature", e)
40+
41+
// Failed path: Not enough parameters
42+
args := [][]byte{[]byte("test")}
43+
if _, err := stub.MockInvoke("1", args); err == nil {
44+
t.Fatalf("escc invoke should have failed with invalid number of args: %v", args)
45+
}
46+
47+
// Failed path: action struct is null
48+
args = [][]byte{[]byte("test"), []byte("action"), []byte("proposal")}
49+
args[1] = nil
50+
if _, err := stub.MockInvoke("1", args); err == nil {
51+
fmt.Println("Invoke", args, "failed", err)
52+
t.Fatalf("escc invoke should have failed with Action object is null. args: %v", args)
53+
}
54+
55+
// Successful path
56+
args = [][]byte{[]byte("dv"), mockAction(), mockProposal()}
57+
if _, err := stub.MockInvoke("1", args); err != nil {
58+
t.Fatalf("escc invoke failed with: %v", err)
59+
}
60+
// TODO: Check sig here when we actually sign
61+
}
62+
63+
func mockAction() []byte {
64+
action := &pb.Action{}
65+
action.ProposalHash = []byte("123")
66+
action.SimulationResult = []byte("read-write set")
67+
payload, _ := proto.Marshal(action)
68+
return payload
69+
}
70+
func mockProposal() []byte {
71+
return []byte("proposal")
72+
}

core/system_chaincode/importsysccs.go

+16
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ import (
2020
"github.com/hyperledger/fabric/core/system_chaincode/api"
2121
//import system chain codes here
2222
"github.com/hyperledger/fabric/bddtests/syschaincode/noop"
23+
"github.com/hyperledger/fabric/core/system_chaincode/escc"
2324
"github.com/hyperledger/fabric/core/system_chaincode/lccc"
25+
"github.com/hyperledger/fabric/core/system_chaincode/vscc"
2426
)
2527

2628
//see systemchaincode_test.go for an example using "sample_syscc"
@@ -38,6 +40,20 @@ var systemChaincodes = []*api.SystemChaincode{
3840
Path: "github.com/hyperledger/fabric/core/system_chaincode/lccc",
3941
InitArgs: [][]byte{[]byte("")},
4042
Chaincode: &lccc.LifeCycleSysCC{},
43+
},
44+
{
45+
Enabled: true,
46+
Name: "escc",
47+
Path: "github.com/hyperledger/fabric/core/system_chaincode/escc",
48+
InitArgs: [][]byte{[]byte("")},
49+
Chaincode: &escc.EndorserOneValidSignature{},
50+
},
51+
{
52+
Enabled: true,
53+
Name: "vscc",
54+
Path: "github.com/hyperledger/fabric/core/system_chaincode/vscc",
55+
InitArgs: [][]byte{[]byte("")},
56+
Chaincode: &vscc.ValidatorOneValidSignature{},
4157
}}
4258

4359
//RegisterSysCCs is the hook for system chaincodes where system chaincodes are registered with the fabric
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
Copyright IBM Corp. 2016 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package vscc
18+
19+
import (
20+
"errors"
21+
"fmt"
22+
23+
"github.com/golang/protobuf/proto"
24+
"github.com/hyperledger/fabric/core/chaincode/shim"
25+
//"github.com/hyperledger/fabric/core/crypto"
26+
pb "github.com/hyperledger/fabric/protos"
27+
)
28+
29+
// ValidatorOneValidSignature implements the default transaction validation policy,
30+
// which is to check the correctness of the read-write set and the endorsement
31+
// signatures
32+
type ValidatorOneValidSignature struct {
33+
}
34+
35+
// Init is called once when the chaincode started the first time
36+
func (vscc *ValidatorOneValidSignature) Init(stub shim.ChaincodeStubInterface) ([]byte, error) {
37+
// best practice to do nothing (or very little) in Init
38+
return nil, nil
39+
}
40+
41+
// Invoke is called to validate the specified block of transactions
42+
// This validation system chaincode will check the read-write set validity and at least 1
43+
// correct endorsement. Later we can create more validation system
44+
// chaincodes to provide more sophisticated policy processing such as enabling
45+
// policy specification to be coded as a transaction of the chaincode and the client
46+
// selecting which policy to use for validation using parameter function
47+
// @return serialized Block of valid and invalid transactions indentified
48+
// Note that Peer calls this function with 2 arguments, where args[0] is the
49+
// function name and args[1] is the block
50+
func (vscc *ValidatorOneValidSignature) Invoke(stub shim.ChaincodeStubInterface) ([]byte, error) {
51+
// args[0] - function name (not used now)
52+
// args[1] - serialized Block object, which contains orderred transactions
53+
args := stub.GetArgs()
54+
if len(args) < 2 {
55+
return nil, errors.New("Incorrect number of arguments")
56+
}
57+
58+
if args[1] == nil {
59+
return nil, errors.New("No block to validate")
60+
}
61+
62+
block := &pb.Block2{}
63+
if err := proto.Unmarshal(args[1], block); err != nil {
64+
return nil, fmt.Errorf("Could not unmarshal block: %s", err)
65+
}
66+
67+
// block.messages is an array, so we can deterministically iterate and
68+
// validate each transaction in order
69+
for _, v := range block.Transactions {
70+
tx := &pb.Transaction{}
71+
72+
// Note: for v1, we do not have encrypted blocks
73+
74+
if err := proto.Unmarshal(v, tx); err != nil {
75+
vscc.invalidate(tx)
76+
} else {
77+
vscc.validate(tx)
78+
}
79+
}
80+
81+
// TODO: fill in after we get the end-to-end v1 skeleton working. Mocked returned value for now
82+
return args[1], nil
83+
}
84+
85+
// Query is here to satisfy the Chaincode interface. We don't need it for this system chaincode
86+
func (vscc *ValidatorOneValidSignature) Query(stub shim.ChaincodeStubInterface) ([]byte, error) {
87+
return nil, nil
88+
}
89+
90+
func (vscc *ValidatorOneValidSignature) validate(tx *pb.Transaction) {
91+
// TODO: fill in after we get the end-to-end v1 skeleton working
92+
}
93+
94+
func (vscc *ValidatorOneValidSignature) invalidate(tx *pb.Transaction) {
95+
// TODO: fill in after we get the end-to-end v1 skeleton working
96+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
Copyright IBM Corp. 2016 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
package vscc
17+
18+
import (
19+
"testing"
20+
21+
"github.com/golang/protobuf/proto"
22+
"github.com/hyperledger/fabric/core/chaincode/shim"
23+
pb "github.com/hyperledger/fabric/protos"
24+
)
25+
26+
func TestInit(t *testing.T) {
27+
v := new(ValidatorOneValidSignature)
28+
stub := shim.NewMockStub("validatoronevalidsignature", v)
29+
30+
if _, err := stub.MockInit("1", nil); err != nil {
31+
t.Fatalf("vscc init failed with %v", err)
32+
}
33+
}
34+
35+
func TestInvoke(t *testing.T) {
36+
v := new(ValidatorOneValidSignature)
37+
stub := shim.NewMockStub("validatoronevalidsignature", v)
38+
39+
// Failed path: Invalid arguments
40+
args := [][]byte{[]byte("dv")}
41+
if _, err := stub.MockInvoke("1", args); err == nil {
42+
t.Fatalf("vscc invoke should have returned incorrect number of args: %v", args)
43+
}
44+
45+
args = [][]byte{[]byte("dv"), []byte("tx")}
46+
args[1] = nil
47+
if _, err := stub.MockInvoke("1", args); err == nil {
48+
t.Fatalf("vscc invoke should have returned no block to validate. Input args: %v", args)
49+
}
50+
51+
// Successful path
52+
args = [][]byte{[]byte("dv"), mockBlock()}
53+
if _, err := stub.MockInvoke("1", args); err != nil {
54+
t.Fatalf("vscc invoke failed with: %v", err)
55+
}
56+
}
57+
58+
func mockBlock() []byte {
59+
block := &pb.Block2{}
60+
payload, _ := proto.Marshal(block)
61+
return payload
62+
}

peer/core.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,8 @@ chaincode:
329329
# whitelist, add "myscc: enable" to the list
330330
system:
331331
lccc: enable
332+
escc: enable
333+
vscc: enable
332334
###############################################################################
333335
#
334336
###############################################################################

0 commit comments

Comments
 (0)