Commit 3f2cb2cf authored by tuand27613's avatar tuand27613
Browse files

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: default avatartuand27613 <tdang@us.ibm.com>
parent 03c4a705
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package escc
import (
"errors"
"github.com/hyperledger/fabric/core/chaincode/shim"
//"github.com/hyperledger/fabric/core/crypto"
)
// EndorserOneValidSignature implements the default endorsement policy, which is to
// sign the proposal hash and the read-write set
type EndorserOneValidSignature struct {
}
// Init is called once when the chaincode started the first time
func (e *EndorserOneValidSignature) Init(stub shim.ChaincodeStubInterface) ([]byte, error) {
// best practice to do nothing (or very little) in Init
return nil, nil
}
// Invoke is called to endorse the specified Proposal
// For now, we sign the input and return the endorsed result. Later we can expand
// the chaincode to provide more sophisticate policy processing such as enabling
// policy specification to be coded as a transaction of the chaincode and Client
// could select which policy to use for endorsement using parameter
// @return signature of Action object or error
// Note that Peer calls this function with 3 arguments, where args[0] is the
// function name and args[1] is the Action object and args[2] is Proposal object
func (e *EndorserOneValidSignature) Invoke(stub shim.ChaincodeStubInterface) ([]byte, error) {
// args[0] - function name (not used now)
// args[1] - serialized Action object
// args[2] - serialized Proposal object (not used)
args := stub.GetArgs()
if len(args) < 3 {
return nil, errors.New("Incorrect number of arguments")
}
if args[1] == nil {
return nil, errors.New("Action object is null")
}
// TODO: since we are just trying to get the end-to-end happy path going, we return a fake signed proposal
// Once the scc interface is updated to have a pointer to the peer SecHelper, we will compute the actual signature
return []byte("true"), nil
//return crypto.sign(args[1])
}
// Query is here to satisfy the Chaincode interface. We don't need it for this system chaincode
func (e *EndorserOneValidSignature) Query(stub shim.ChaincodeStubInterface) ([]byte, error) {
return nil, nil
}
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package escc
import (
"fmt"
"testing"
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos"
)
func TestInit(t *testing.T) {
e := new(EndorserOneValidSignature)
stub := shim.NewMockStub("endorseronevalidsignature", e)
if _, err := stub.MockInit("1", nil); err != nil {
fmt.Println("Init failed", err)
t.FailNow()
}
}
func TestInvoke(t *testing.T) {
e := new(EndorserOneValidSignature)
stub := shim.NewMockStub("endorseronevalidsignature", e)
// Failed path: Not enough parameters
args := [][]byte{[]byte("test")}
if _, err := stub.MockInvoke("1", args); err == nil {
t.Fatalf("escc invoke should have failed with invalid number of args: %v", args)
}
// Failed path: action struct is null
args = [][]byte{[]byte("test"), []byte("action"), []byte("proposal")}
args[1] = nil
if _, err := stub.MockInvoke("1", args); err == nil {
fmt.Println("Invoke", args, "failed", err)
t.Fatalf("escc invoke should have failed with Action object is null. args: %v", args)
}
// Successful path
args = [][]byte{[]byte("dv"), mockAction(), mockProposal()}
if _, err := stub.MockInvoke("1", args); err != nil {
t.Fatalf("escc invoke failed with: %v", err)
}
// TODO: Check sig here when we actually sign
}
func mockAction() []byte {
action := &pb.Action{}
action.ProposalHash = []byte("123")
action.SimulationResult = []byte("read-write set")
payload, _ := proto.Marshal(action)
return payload
}
func mockProposal() []byte {
return []byte("proposal")
}
......@@ -20,7 +20,9 @@ import (
"github.com/hyperledger/fabric/core/system_chaincode/api"
//import system chain codes here
"github.com/hyperledger/fabric/bddtests/syschaincode/noop"
"github.com/hyperledger/fabric/core/system_chaincode/escc"
"github.com/hyperledger/fabric/core/system_chaincode/lccc"
"github.com/hyperledger/fabric/core/system_chaincode/vscc"
)
//see systemchaincode_test.go for an example using "sample_syscc"
......@@ -38,6 +40,20 @@ var systemChaincodes = []*api.SystemChaincode{
Path: "github.com/hyperledger/fabric/core/system_chaincode/lccc",
InitArgs: [][]byte{[]byte("")},
Chaincode: &lccc.LifeCycleSysCC{},
},
{
Enabled: true,
Name: "escc",
Path: "github.com/hyperledger/fabric/core/system_chaincode/escc",
InitArgs: [][]byte{[]byte("")},
Chaincode: &escc.EndorserOneValidSignature{},
},
{
Enabled: true,
Name: "vscc",
Path: "github.com/hyperledger/fabric/core/system_chaincode/vscc",
InitArgs: [][]byte{[]byte("")},
Chaincode: &vscc.ValidatorOneValidSignature{},
}}
//RegisterSysCCs is the hook for system chaincodes where system chaincodes are registered with the fabric
......
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package vscc
import (
"errors"
"fmt"
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/core/chaincode/shim"
//"github.com/hyperledger/fabric/core/crypto"
pb "github.com/hyperledger/fabric/protos"
)
// ValidatorOneValidSignature implements the default transaction validation policy,
// which is to check the correctness of the read-write set and the endorsement
// signatures
type ValidatorOneValidSignature struct {
}
// Init is called once when the chaincode started the first time
func (vscc *ValidatorOneValidSignature) Init(stub shim.ChaincodeStubInterface) ([]byte, error) {
// best practice to do nothing (or very little) in Init
return nil, nil
}
// Invoke is called to validate the specified block of transactions
// This validation system chaincode will check the read-write set validity and at least 1
// correct endorsement. Later we can create more validation system
// chaincodes to provide more sophisticated policy processing such as enabling
// policy specification to be coded as a transaction of the chaincode and the client
// selecting which policy to use for validation using parameter function
// @return serialized Block of valid and invalid transactions indentified
// Note that Peer calls this function with 2 arguments, where args[0] is the
// function name and args[1] is the block
func (vscc *ValidatorOneValidSignature) Invoke(stub shim.ChaincodeStubInterface) ([]byte, error) {
// args[0] - function name (not used now)
// args[1] - serialized Block object, which contains orderred transactions
args := stub.GetArgs()
if len(args) < 2 {
return nil, errors.New("Incorrect number of arguments")
}
if args[1] == nil {
return nil, errors.New("No block to validate")
}
block := &pb.Block2{}
if err := proto.Unmarshal(args[1], block); err != nil {
return nil, fmt.Errorf("Could not unmarshal block: %s", err)
}
// block.messages is an array, so we can deterministically iterate and
// validate each transaction in order
for _, v := range block.Transactions {
tx := &pb.Transaction{}
// Note: for v1, we do not have encrypted blocks
if err := proto.Unmarshal(v, tx); err != nil {
vscc.invalidate(tx)
} else {
vscc.validate(tx)
}
}
// TODO: fill in after we get the end-to-end v1 skeleton working. Mocked returned value for now
return args[1], nil
}
// Query is here to satisfy the Chaincode interface. We don't need it for this system chaincode
func (vscc *ValidatorOneValidSignature) Query(stub shim.ChaincodeStubInterface) ([]byte, error) {
return nil, nil
}
func (vscc *ValidatorOneValidSignature) validate(tx *pb.Transaction) {
// TODO: fill in after we get the end-to-end v1 skeleton working
}
func (vscc *ValidatorOneValidSignature) invalidate(tx *pb.Transaction) {
// TODO: fill in after we get the end-to-end v1 skeleton working
}
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package vscc
import (
"testing"
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos"
)
func TestInit(t *testing.T) {
v := new(ValidatorOneValidSignature)
stub := shim.NewMockStub("validatoronevalidsignature", v)
if _, err := stub.MockInit("1", nil); err != nil {
t.Fatalf("vscc init failed with %v", err)
}
}
func TestInvoke(t *testing.T) {
v := new(ValidatorOneValidSignature)
stub := shim.NewMockStub("validatoronevalidsignature", v)
// Failed path: Invalid arguments
args := [][]byte{[]byte("dv")}
if _, err := stub.MockInvoke("1", args); err == nil {
t.Fatalf("vscc invoke should have returned incorrect number of args: %v", args)
}
args = [][]byte{[]byte("dv"), []byte("tx")}
args[1] = nil
if _, err := stub.MockInvoke("1", args); err == nil {
t.Fatalf("vscc invoke should have returned no block to validate. Input args: %v", args)
}
// Successful path
args = [][]byte{[]byte("dv"), mockBlock()}
if _, err := stub.MockInvoke("1", args); err != nil {
t.Fatalf("vscc invoke failed with: %v", err)
}
}
func mockBlock() []byte {
block := &pb.Block2{}
payload, _ := proto.Marshal(block)
return payload
}
......@@ -329,6 +329,8 @@ chaincode:
# whitelist, add "myscc: enable" to the list
system:
lccc: enable
escc: enable
vscc: enable
###############################################################################
#
###############################################################################
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment