Is initChain method useless in the file peer.go hyperledger fabric? - hyperledger-fabric

When we invoke command peer node start to start peer node, or
command peer join channel -c xxx.block , it will invoke peer.InitChain(chainID) method in the peer.go file,
but I think the code is useless . I annotation it,and peer node doesn't have any problem. As the system code such lscc、cscc、qscc and so on have been started using peer.go file following code:
//initialize system chaincodes
initSysCCs()
so I think the file peer.go has the useless method InitChain(cid string) ?
the method will use the system chaincode in exectransaction.go with method
//Execute - execute proposal, return original response of chaincode
func Execute(ctxt context.Context, cccid *ccprovider.CCContext, spec interface{}) (*pb.Response, *pb.ChaincodeEvent, error) {
and finnally reaches to chaincode_support.go,
if notfy, err = chrte.handler.sendExecuteMessage(ctxt, cccid.ChainID, msg, cccid.SignedProposal, cccid.Proposal); err != nil {
return nil, fmt.Errorf("Error sending %s: %s", msg.Type.String(), err)
}
chainID doesn't affect handler to deal with,and the invoke following:
func (handler *Handler) sendExecuteMessage(ctxt context.Context, chainID string, msg *pb.ChaincodeMessage, signedProp *pb.SignedProposal, prop *pb.Proposal) (chan *pb.ChaincodeMessage, error) {
txctx, err := handler.createTxContext(ctxt, chainID, msg.Txid, signedProp, prop)
if err != nil {
return nil, err
}
if chaincodeLogger.IsEnabledFor(logging.DEBUG) {
chaincodeLogger.Debugf("[%s]Inside sendExecuteMessage. Message %s", shorttxid(msg.Txid), msg.Type.String())
}
//if security is disabled the context elements will just be nil
if err = handler.setChaincodeProposal(signedProp, prop, msg); err != nil {
return nil, err
}
chaincodeLogger.Debugf("[%s]sendExecuteMsg trigger event %s", shorttxid(msg.Txid), msg.Type)
handler.triggerNextState(msg, true) //**when triggerNextState, chainId field is useless.**
return txctx.responseNotifier, nil
}

If you referring to the the peer.InitChain(cid string) method, so I do not think it's useless. Honestly I'm not completely sure about your explanation as it's a bit hard to follow, but this function being used upon peer initialization. E.g. the function being called from peer.Initialize(init func(string)) method to be precise here is the line:
// Skipped rest of the code
// Create a chain if we get a valid ledger with config block
if err = createChain(cid, ledger, cb); err != nil {
peerLogger.Warningf("Failed to load chain %s(%s)", cid, err)
peerLogger.Debugf("Error reloading chain %s with message %s. We continue to the next chain rather than abort.", cid, err)
continue
}
InitChain(cid)
}
The role of this method is to call for initializer which being passed in start.go:
//this brings up all the chains (including testchainid)
peer.Initialize(func(cid string) {
logger.Debugf("Deploying system CC, for chain <%s>", cid)
scc.DeploySysCCs(cid)
})
basically deploying system chaincodes. Please note that in peer.Initialize method assigns chainInializer, which is called via peer.InitChain.
func Initialize(init func(string)) {
chainInitializer = init
var cb *common.Block
var ledger ledger.PeerLedger
ledgermgmt.Initialize()
ledgerIds, err := ledgermgmt.GetLedgerIDs()
if err != nil {
panic(fmt.Errorf("Error in initializing ledgermgmt: %s", err))
}
So to your question, no this is not useless code. Also note to the difference:
//initialize system chaincodes
initSysCCs()
implemented as following:
func initSysCCs() {
//deploy system chaincodes
scc.DeploySysCCs("")
logger.Infof("Deployed system chaincodes")
}
note the fact that chainID=="", while following code:
//this brings up all the chains (including testchainid)
peer.Initialize(func(cid string) {
logger.Debugf("Deploying system CC, for chain <%s>", cid)
scc.DeploySysCCs(cid)
})
deploys chaincode for specific channel id, e.g. scc.DeploySysCCs(cid).
Going down the path you can spot the difference at sysccapi.go, where deploySysCC implemented as:
// deploySysCC deploys the given system chaincode on a chain
func deploySysCC(chainID string, syscc *SystemChaincode) error {
if !syscc.Enabled || !isWhitelisted(syscc) {
sysccLogger.Info(fmt.Sprintf("system chaincode (%s,%s) disabled", syscc.Name, syscc.Path))
return nil
}
var err error
ccprov := ccprovider.GetChaincodeProvider()
txid := util.GenerateUUID()
ctxt := context.Background()
if chainID != "" {
lgr := peer.GetLedger(chainID)
if lgr == nil {
panic(fmt.Sprintf("syschain %s start up failure - unexpected nil ledger for channel %s", syscc.Name, chainID))
}
//init can do GetState (and other Get's) even if Puts cannot be
//be handled. Need ledger for this
ctxt2, txsim, err := ccprov.GetContext(lgr, txid)
if err != nil {
return err
}
ctxt = ctxt2
defer txsim.Done()
}
chaincodeID := &pb.ChaincodeID{Path: syscc.Path, Name: syscc.Name}
spec := &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeId: chaincodeID, Input: &pb.ChaincodeInput{Args: syscc.InitArgs}}
// First build and get the deployment spec
chaincodeDeploymentSpec, err := buildSysCC(ctxt, spec)
if err != nil {
sysccLogger.Error(fmt.Sprintf("Error deploying chaincode spec: %v\n\n error: %s", spec, err))
return err
}
version := util.GetSysCCVersion()
cccid := ccprov.GetCCContext(chainID, chaincodeDeploymentSpec.ChaincodeSpec.ChaincodeId.Name, version, txid, true, nil, nil)
_, _, err = ccprov.ExecuteWithErrorFilter(ctxt, cccid, chaincodeDeploymentSpec)
sysccLogger.Infof("system chaincode %s/%s(%s) deployed", syscc.Name, chainID, syscc.Path)
return err
}
Note the following peace of code inside:
ctxt := context.Background()
if chainID != "" {
lgr := peer.GetLedger(chainID)
if lgr == nil {
panic(fmt.Sprintf("syschain %s start up failure - unexpected nil ledger for channel %s", syscc.Name, chainID))
}
//init can do GetState (and other Get's) even if Puts cannot be
//be handled. Need ledger for this
ctxt2, txsim, err := ccprov.GetContext(lgr, txid)
if err != nil {
return err
}
ctxt = ctxt2
defer txsim.Done()
}

Related

Validation System Chaincode of Hyperledger Fabric

Build new VSCC plugin with minor revision in the existing VSCC codebase and integrate the same with chain code deployment process.
2)Identify the interface point where VSCC code is receiving blocks from orderer nodes and send the details to a dummy webserver application.
How to implement this for hyperledger fabric network setup
Is this the interface for receiving block details from the orderer:
func (vscc *Validator) Validate(
block *common.Block,
namespace string,
txPosition int,
actionPosition int,
policyBytes []byte,
) commonerrors.TxValidationError {
vscc.stateBasedValidator.PreValidate(uint64(txPosition), block)
va, err := vscc.extractValidationArtifacts(block, txPosition, actionPosition)
if err != nil {
vscc.stateBasedValidator.PostValidate(namespace, block.Header.Number, uint64(txPosition), err)
return policyErr(err)
}
txverr := vscc.stateBasedValidator.Validate(
namespace,
block.Header.Number,
uint64(txPosition),
va.rwset,
va.prp,
policyBytes,
va.endorsements,
)
if txverr != nil {
logger.Errorf("VSCC error: stateBasedValidator.Validate failed, err %s", txverr)
vscc.stateBasedValidator.PostValidate(namespace, block.Header.Number, uint64(txPosition), txverr)
return txverr
}
// do some extra validation that is specific to lscc
if namespace == "lscc" {
logger.Debugf("VSCC info: doing special validation for LSCC")
err := vscc.ValidateLSCCInvocation(va.chdr.ChannelId, va.env, va.cap, va.payl, vscc.capabilities)
if err != nil {
logger.Errorf("VSCC error: ValidateLSCCInvocation failed, err %s", err)
vscc.stateBasedValidator.PostValidate(namespace, block.Header.Number, uint64(txPosition), err)
return err
}
}
vscc.stateBasedValidator.PostValidate(namespace, block.Header.Number, uint64(txPosition), nil)
return nil
}

Azure sdk for go - code can't make it passed compute.VirtualMachinesClient.ListAllComplete()

I'm testing a function I have that gets all azure vms under a specific subscription.
It uses azure sdk for go's compute.VirtualMachinesClient to do so.
My problem is with the vm clients ListAllComplete function.
It's not returning an error. The code just doesn't seem to be able to make it passed that line.
Any suggestions on the source of the problem would be appreciated.
This is the code, I've used the fmt package to follow how far it gets:
func GetAllAzureVms() ([]compute.VirtualMachine, error) {
fmt.Printf("In getAllAzureVm\n")
var vmList []compute.VirtualMachine
vmClient, err := GetAzureVmClient()
fmt.Printf("Out of GetAzureVmClient\n")
if err != nil {
return nil, err
}
fmt.Print("No error from getazurevmclient\n")
vmListComplete, err := vmClient.ListAllComplete(context.Background(), "statusOnly=false")
fmt.Print("vmClient.ListAllComplete done")
if err != nil {
fmt.Print("vmClient.ListAllComplete error")
return nil, err
}
fmt.Print("here")
for vmListComplete.NotDone() {
vmList = append(vmList, vmListComplete.Value())
err := vmListComplete.NextWithContext(context.Background())
if err != nil {
return nil, err
}
}
fmt.Print("here2")
return vmList, nil
}
It cant make it passed the line:
vmListComplete, err := vmClient.ListAllComplete(context.Background(), "statusOnly=false")
No error is returned.
I have a similar piece of code, not for vmClient unluckily, but for securityCustomRules.
What I've found useful was to use ListComplete() instead of ListAll() and the print values through JSON marhsalling.
I hope you can find it useful anyway.
import (
"context"
"fmt"
"os"
"testing"
"github.com/gruntwork-io/terratest/modules/azure"
"github.com/gruntwork-io/terratest/modules/terraform"
)
securityCustomRulesList, err := securityCustomRulesClient.ListComplete(context.Background(), tfResourceGroupName, tfVnetName+"-"+fmt.Sprint(vnetIndex)+"-subnet-02-nsg")
// - Scan iterator items [https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network#ApplicationGatewayListResultIterator]
if err != nil {
fmt.Fprintf(os.Stderr, ">>>> Error parsing securityCustomRulesClient:: %s", err)
return
}
for securityCustomRulesList.NotDone() {
// securityCustomRulesList.Value() -> securityRule [https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network#SecurityRule]
v := securityCustomRulesList.Value()
vJson, _ := v.MarshalJSON()
fmt.Printf(">> Network securityCustomRulesList JSON %s \n", string(vJson))
//fmt.Printf(">> Network securityCustomRulesList %s - %s\n", *v.Name, *v.SecurityRulePropertiesFormat.Description)
securityCustomRulesList.NextWithContext(context.Background())
}
Which gives me an output like:
>> Creating security custom rules list instance 'securityCustomRulesList'..
>> Network securityCustomRulesList JSON {"id":"/subscriptions/8f7d6be2/resourceGroups/unit-tests-tfm-azure-network-resource-group/providers/Microsoft.Network/networkSecurityGroups/unit-tests-tfm-azure-network-vnet-0-subnet-02-nsg/securityRules/test-02","name":"test-02","properties":{"access":"Deny","description":"Deny access","destinationAddressPrefix":"10.0.2.1","destinationAddressPrefixes":[],"destinationPortRange":"*","destinationPortRanges":[],"direction":"Inbound","priority":111,"protocol":"*","sourceAddressPrefix":"10.0.1.0/24","sourceAddressPrefixes":[],"sourcePortRange":"*","sourcePortRanges":[]}}
Useful links:
Here you can find a complete usage example from the official terratest/azure module: https://github.com/gruntwork-io/terratest/blob/dae956eb39e91dfb00f3ba85060a6dbf58c6782b/modules/azure/nsg.go
https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network#SecurityRule.MarshalJSON

AT commands exchange with /dev/tty*

I have a device with a GPRS onboard. GPRS connects with the third-party application and it works. I need to know the signal strength of the connection, so, I use ATZ, then AT+CSQ commands. When I work using some terminal software it works. Then, I had tried to use https://github.com/ishuah/bifrost soft as a terminal. It works as well. But how can I simply communicate with a device, not using terminal, without re-connection or connection abortion, etc?
I tried simply echo ATZ > /dev/ttyX - no answer
// This writes, but reads only zeros (((
package main
import (
"github.com/jacobsa/go-serial/serial"
"io"
"log"
"time"
"fmt"
)
func Sleep(duration int) {
time.Sleep(time.Second * time.Duration(duration))
}
func printBuf(b []byte){
for _, val:=range b {
fmt.Printf("%x ", val)
}
}
func main(){
options := serial.OpenOptions{
PortName: "/dev/ttyX",
BaudRate: 115200,
DataBits: 8,
StopBits: 1,
MinimumReadSize: 0,
InterCharacterTimeout: 50,
}
port, err := serial.Open(options)
if err != nil {
log.Printf("port.Read: %v", err)
return
}
// Make sure to close it later.
defer port.Close()
var s string = `AT+CSQ`
b:=[]byte(s)
n, err := port.Write(b)
if err != nil {
log.Printf("port.Write: %v", err)
}
log.Println("Written bytes: ", n)
//Sleep(1)
res := make([]byte, 64)
n, err = port.Read(res)
if err != nil && err != io.EOF {
log.Printf("port.Read: %v", err)
}
log.Println("READ bytes: ", n)
printBuf(res)
}
/*
I expect (for example):
---------
ATZ
OK
AT+CSQ
+CSQ 22.4
*/
Most serial devices need a termination character to react to the commands they receive.
If you add it, your code should work:
var s string = `AT+CSQ\r`
I don't see any other differences from your code and sending a command using a serial terminal. The same should apply when you echo the command directly onto the port file descriptor.

Read media keys from Go program

I am writing a media cross-platform distributed media player for use on my own network.
The current version has three/four parts:
A NAS holding the audio files.
A metadata server holding information about the files.
A HTML/JS client that allows manipulation of the metadata server and queuing media for the:
A player deamon.
My problem lies with part 4. The player has no UI, nor does it need one. It will be controlled via network commands from the client and by listening to the media keys on its current host.
The player daemon needs to work on both Windows and Linux, but I can't seem to figure out a way (any way) to read these keys on either OS. Most of the way I know to read the keyboard will not read these keys at all.
With the help of several commenters, I now have it all figured out.
The Linux version is as follows:
package main
import (
“bytes”
“encoding/binary”
“fmt”
“os”
“os/exec”
“syscall”
)
// parses through the /proc/bus/input/devices file for keyboard devices.
// Copied from `github.com/gearmover/keylogger` with trivial modification.
func dumpDevices() ([]string, error) {
cmd := exec.Command(“/bin/sh”, “-c”, “/bin/grep -E ‘Handlers|EV=’ /proc/bus/input/devices | /bin/grep -B1 ‘EV=120013’ | /bin/grep -Eo ‘event[0-9]+’”)
output, err := cmd.Output()
if err != nil {
return nil, err
}
buf := bytes.NewBuffer(output)
var devices []string
for line, err := buf.ReadString(‘\n’); err == nil; {
devices = append(devices, “/dev/input/”+line[:len(line)-1])
line, err = buf.ReadString(‘\n’)
}
return devices, nil
}
// Using MS names, just because I don’t feel like looking up the Linux versions.
var keys = map[uint16]string{
0xa3: “VK_MEDIA_NEXT_TRACK”,
0xa5: “VK_MEDIA_PREV_TRACK”,
0xa6: “VK_MEDIA_STOP”,
0xa4: “VK_MEDIA_PLAY_PAUSE”,
}
// Most of the code here comes from `github.com/gearmover/keylogger`.
func main() {
// drop privileges when executing other programs
syscall.Setgid(65534)
syscall.Setuid(65534)
// dump our keyboard devices from /proc/bus/input/devices
devices, err := dumpDevices()
if err != nil {
fmt.Println(err)
}
if len(devices) == 0 {
fmt.Println(“No input devices found”)
return
}
// bring back our root privs
syscall.Setgid(0)
syscall.Setuid(0)
// Open the first keyboard device.
input, err := os.OpenFile(devices[0], os.O_RDONLY, 0600)
if err != nil {
fmt.Println(err)
return
}
defer input.Close()
// Log media keys
var buffer = make([]byte, 24)
for {
// read the input events as they come in
n, err := input.Read(buffer)
if err != nil {
return
}
if n != 24 {
fmt.Println(“Weird Input Event Size: “, n)
continue
}
// parse the input event according to the <linux/input.h> header struct
binary.LittleEndian.Uint64(buffer[0:8]) // Time stamp stuff I could care less about
binary.LittleEndian.Uint64(buffer[8:16])
etype := binary.LittleEndian.Uint16(buffer[16:18]) // Event Type. Always 1 for keyboard events
code := binary.LittleEndian.Uint16(buffer[18:20]) // Key scan code
value := int32(binary.LittleEndian.Uint32(buffer[20:24])) // press(1), release(0), or repeat(2)
if etype == 1 && value == 1 && keys[code] != “” {
// In a real application I would send a message here.
fmt.Println(keys[code])
}
}
}
And the Windows version:
package main
import (
“fmt”
“syscall”
“time”
)
var user32 = syscall.NewLazyDLL(“user32.dll”)
var procGAKS = user32.NewProc(“GetAsyncKeyState”)
// Key codes from MSDN
var keys = [4]uint{
0xb0, // VK_MEDIA_NEXT_TRACK
0xb1, // VK_MEDIA_PREV_TRACK
0xb2, // VK_MEDIA_STOP
0xb3, // VK_MEDIA_PLAY_PAUSE
}
var names = [4]string{
“VK_MEDIA_NEXT_TRACK”,
“VK_MEDIA_PREV_TRACK”,
“VK_MEDIA_STOP”,
“VK_MEDIA_PLAY_PAUSE”,
}
func main() {
fmt.Println(“Running…”)
// Since I don’t want to trigger dozens of times for each key I need to track state.
// I could check the bits of GAKS’ return value, but that is not reliable.
down := [4]bool{false, false, false, false}
for {
time.Sleep(1 * time.Millisecond)
for i, key := range keys {
// val is not a simple boolean!
// 0 means “not pressed” (also certain errors)
// If LSB is set the key was just pressed (this may not be reliable)
// If MSB is set the key is currently down.
val, _, _ := procGAKS.Call(uintptr(key))
// Turn a press into a transition and track key state.
goingdown := false
if int(val) != 0 && !down[i] {
goingdown = true
down[i] = true
}
if int(val) == 0 && down[i] {
down[i] = false
}
if goingdown {
// In a real application I would send a message here.
fmt.Println(names[i])
}
}
}
}
The only "issue" is that the Linux version must be run as root. For me this is not a problem. If running as root is a problem I think there is a way that involves X11...

go websockets eof

I'm trying to make a simple command forwarder to connect my home computer to a server I own, so that I can push commands to my server and my home pc gets it. Those commands are simple pause/resume for my downloader. My design is, that on a server, I run a hub instance, which creates a window for passing commands and a window for backend to pass those commands to my pc. I'm bounding those two "windows" with a channel, they run a server. When a client connects and sends a message to the hub, it gets streamed through a channel to backend window and then to the real backend (on my home pc). When backend responds to the backend window on the hub, the hub prints the result back to the client.
With this approach, only the first message passes and works with my downloader. I have to reconnect the backend from my home pc with the hub each time I get a message to get this working properly. I don't think that's the proper way with websockets, so here I am. After one successful request (when the backend finishes it's work and replies the result), it gets looped forever with EOF error.
The important parts of the code are:
main executable
hub handlers
backend connector
If you put the source in your GOPATH (i'm developing it for the tip version of go to support modern websockets), to compile it:
go build gosab/cmd, to run it:
./cmd -mode="hub" hub
./cmd -mode="backend" --address="localhost:8082" backend
To pass messages to the hub, use this javascript:
var s = new WebSocket("ws://localhost:8082")
s.send("1 5")
So how do I handle it? Are channels a good way to communicate between two different requests?
I'm surprised you haven't received an answer to this.
What you need to do is something like the code below. When you receive an incoming websocket connection, a new goroutine is spawned for that connection. If you let that goroutine end, it'll disconnect the websocket client.
I'm making an assumption that you're not necessarily going to be running the client and server on the same computer. If you always are, then it'd be better to do the communication internally via channels or such instead of using websockets or a network port. I only mention this because I'm not completely sure what you're using this for. I just hope I answered the right part of your question.
package main
import (
"code.google.com/p/go.net/websocket"
"flag"
"fmt"
"net/http"
"os"
"time"
)
type Message struct {
RequestID int
Command string
SomeOtherThing string
Success bool
}
var mode *string = flag.String("mode", "<nil>", "Mode: server or client")
var address *string = flag.String("address", "localhost:8080", "Bind address:port")
func main() {
flag.Parse()
switch *mode {
case "server":
RunServer()
case "client":
RunClient()
default:
flag.Usage()
}
}
func RunServer() {
http.Handle("/", http.FileServer(http.Dir("www")))
http.Handle("/server", websocket.Handler(WSHandler))
fmt.Println("Starting Server")
err := http.ListenAndServe(*address, nil)
if err != nil {
fmt.Printf("HTTP failed: %s\n", err.Error())
os.Exit(1)
}
}
func WSHandler(ws *websocket.Conn) {
defer ws.Close()
fmt.Println("Client Connected")
for {
var message Message
err := websocket.JSON.Receive(ws, &message)
if err != nil {
fmt.Printf("Error: %s\n", err.Error())
return
}
fmt.Println(message)
// do something useful here...
response := new(Message)
response.RequestID = message.RequestID
response.Success = true
response.SomeOtherThing = "The hot dog left the castle as requested."
err = websocket.JSON.Send(ws, response)
if err != nil {
fmt.Printf("Send failed: %s\n", err.Error())
os.Exit(1)
}
}
}
func RunClient() {
fmt.Println("Starting Client")
ws, err := websocket.Dial(fmt.Sprintf("ws://%s/server", *address), "", fmt.Sprintf("http://%s/", *address))
if err != nil {
fmt.Printf("Dial failed: %s\n", err.Error())
os.Exit(1)
}
incomingMessages := make(chan Message)
go readClientMessages(ws, incomingMessages)
i := 0
for {
select {
case <-time.After(time.Duration(2e9)):
i++
response := new(Message)
response.RequestID = i
response.Command = "Eject the hot dog."
err = websocket.JSON.Send(ws, response)
if err != nil {
fmt.Printf("Send failed: %s\n", err.Error())
os.Exit(1)
}
case message := <-incomingMessages:
fmt.Println(message)
}
}
}
func readClientMessages(ws *websocket.Conn, incomingMessages chan Message) {
for {
var message Message
err := websocket.JSON.Receive(ws, &message)
if err != nil {
fmt.Printf("Error: %s\n", err.Error())
return
}
incomingMessages <- message
}
}

Resources