How do I include my own tracer file into eth/tracers for go-eth? - go-ethereum

I've modified the call_tracer.js file (https://github.com/ethereum/go-ethereum/tree/master/eth/tracers/internal/tracers)for my own requirements, however I'm unsure as to how include it along with the other tracers.
Right now, I'm feeding my tracer JS code as an input for debug_traceCall as below:
TxObj_TraceConfig := DebugTraceCallTraceConfig{
Tracer: "{My TRACER JS CODE}",
}
var raw json.RawMessage
err := rpcClient.CallContext(context.Background(), &raw, "debug_traceCall", TxObj, "latest", TxObj_TraceConfig)
var res DebugTraceCallTraceResponse
json.Unmarshal(raw, &res)
I'd like to instead specify the Tracer file as you do usually i.e. Tracer :"callTracer" or in my case Tracer : "customTracer".
I'm assuming that I will need to include my Tracer in assets.go ?

It should be sufficient to place the *.js file into the go-ethereum/eth/tracers/js/internal/tracers/tracers/ directory.
The code in tracers.go should include all JS files into the geth binary and make it available as the filename without the extension.

Related

Bazel: how to get the path of a binary that I built along a bazel test

I'm writing a go test with bazel. The test will build a binary first, and mount the binary to a docker container. So I need to know the path of the binary I built.
The file system structure is like this:
The dir structure looks like the following:
some/of/my/path
├── BUILD.bazel
├── my_test.go
└── my_tool
├── BUILD.bazel
└── my_tool.go
where I'd like to build a go binary with go files at my_tool dir.
From my previous question's answer, I got to know that I can use the data entry of in go_test from some/of/my/path/BUILD.bazel to build the binary:
go_test(
name = "my_test",
srcs = ["my_test.go"],
data = glob(["testdata/**"]) + [
"//some/of/my/path/my_tool:my_tool",
],
gotags = ["my_test"],
deps = [
"//pkg/util/contextutil",
"//pkg/util/log",
...
],
)
which did build the go binary for my_tool. But now the question is, how do I know where is the built binary of my_tool in my_test.go?
In my_test.go, I need to write something like this:
package my_lucky_test
...
pathForMyTool := some_path
hostConfig := container.HostConfig{
Binds := []string {""%s/my_tool-bin:/workding-dir/my_tool-bin", pathForMyTool"}
}
My question is how can I get the absolute path of "my_tool-bin"?
Simply run;
bazel build //some/of/my/path:my_test
It should print out the path of the binary to stdout.
As an alternative to your current approach might I suggest that you make use of bazelbuild/rules_docker#go_image which is a Bazel aware method for building containers.
EDIT: OP has clarified the question, though I am leaving the original answer above as others may find it useful.
When you bundle a binary/test with some data, the files under the data attribute become a set of 'runfiles'. There are various libraries in each language for resolving runfiles. For golang you'll want to use the bazel pkg in rules_go, to resolve your runfiles. e.g.
go_test(
name = "my_test",
srcs = ["my_test.go"],
data = glob(["testdata/**"]) + [
"//some/of/my/path/my_tool:my_tool",
],
gotags = ["my_test"],
deps = [
"//pkg/util/contextutil",
"//pkg/util/log",
# NEW dep
"#rules_go//rules_go/go/tools/bazel",
...
],
)
Your my_test.go;
package my_lucky_test
# NEW
import(
"github.com/bazelbuild/rules_go/go/tools/bazel"
)
#...
pathForMyTool, ok := bazel.FindBinary("some/of/my/path/my_tool", "my_tool")
if !ok {
# Error handling
}
hostConfig := container.HostConfig{
Binds := []string {""%s/my_tool-bin:/workding-dir/my_tool-bin", pathForMyTool}
}

Golang kubernetes client - patching an existing resource with a label

I want to patch an existing secret resource within Kubernetes. The object is called centos-secretstorage within the default namespace. I want to add a simple label of test: empty. However, this fails when the secret object centos-secretstorage exists, but it doesn't have any existing labels. If I manually label the secret with something else beforehand via kubectl label centos-secretstorage hello=world, and rerun my golang code. It is able to add the test: empty label successfully.
However, I want to have this be able to add a label regardless if existing labels exist or not.
type secret struct {
namespace string
name string
}
func main() {
k8sClient := k8CientInit()
vaultSecret := secret{
namespace: "default",
name: "centos-secretstorage",
}
vaultSecret.patchSecret(k8sClient)
}
type patchStringValue struct {
Op string `json:"op"`
Path string `json:"path"`
Value string `json:"value"`
}
func (p *secret) patchSecret(k8sClient *kubernetes.Clientset) {
emptyPayload := []patchStringValue{{
Op: "add",
Path: "/metadata/labels/test",
Value: "empty",
}}
emptyPayloadBytes, _ := json.Marshal(emptyPayload)
fmt.Println(string(emptyPayloadBytes))
emptyres, emptyerr := k8sClient.CoreV1().Secrets(p.namespace).Patch(p.name, types.JSONPatchType, emptyPayloadBytes)
if emptyerr != nil {
log.Fatal(emptyerr.Error())
}
fmt.Println(emptyres.Labels)
}
Error: the server rejected our request due to an error in our request
The problem is that the add operation in the JSON patch strategy requires the path to point to an existing map, while the object you are patching does not have this map at all. This is why when any label exists, the patch succeeds. We can work around this by using a different patch strategy. I think the merge strategy should work well.
I was able to reproduce this (on a namespace, but the object doesn't matter) using kubectl (which is generally useful when debugging the Kubernetes API):
kubectl patch ns a --type='json' -p='[{"op": "merge", "path": "/metadata/labels/test", "value":"empty"}]' -> fails
kubectl patch ns a --type='merge' -p='{"metadata": {"labels": {"test": "empty"}}}' -> succeeds
Using Golang client-go it would look something like this (didn't actually compile / run this):
payload := `{"metadata": {"labels": {"test": "empty"}}}`
emptyres, emptyerr := k8sClient.CoreV1().Secrets(p.namespace).Patch(p.name, types.MergePatchType, []byte(payload))
You can make the creation of the payload JSON nicer using structs, as you did with patchStringValue.
More info on patch strategies can be found here:
https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/
https://erosb.github.io/post/json-patch-vs-merge-patch/

How to serve index.html on non root path using golang

I want to serve my angular app index.html under localhost:3000/mypath/ is there a way to accomplish that?
package main
import (
"net/http"
)
func main() {
// This works
http.Handle("/", http.FileServer(http.Dir("./my-project/dist/")))
// This doesn't work, you get 404 page not found
http.Handle("/mypath/", http.FileServer(http.Dir("./my-project/dist/")))
http.ListenAndServe(":3000", nil)
}
Remove the / handler, and change the /mypath/ handler into code below:
http.Handle("/mypath/", http.StripPrefix("/mypath/", http.FileServer(http.Dir("./my-project/dist/"))))
The http.StripPrefix() function is used to remove the prefix of requested path. On your current /mypath handler, every request will be prefixed with /mypath/. Take a look at example below.
/mypath/index.html
/mypath/some/folder/style.css
...
If the requested url path is not stripped, then (as per above example) it'll point into below respective locations, which is INVALID path and will result file not found error.
./my-project/dist/mypath/index.html
./my-project/dist/mypath/some/folder/style.css
...
By stripping the /mypath, it'll point into below locations, the correct one.
./my-project/dist/index.html
./my-project/dist/some/folder/style.css
...

Mocha test failing using babel and webpack

So I am using webpack, babel, and mocha here. When I have code like this:
import userImage from '../../images/user.png';
and I build with webpack, userImage results in a string to the path of the file since I am using the file loader for images (requirements call for me not to embed images) however when I try to run my mocha tests using:
./node_modules/.bin/babel-node ./node_modules/.bin/babel-istanbul cover ./node_modules/.bin/_mocha
I get a syntax error:
SyntaxError: /repositories/react-seed/web/app/images/user.png: Unexpected character '�' (1:0)
> 1 | �PNG
| ^
2 |
3 |
I also get this error when removing istanbul. So it seems like it is trying to load the actually image file however can parse it as JavaScript since it is not.
Anyone know a way around this issue?
You can use the --compilers option which allows you to customize the nodejs require system in order to let it understand png files. So :
mocha --compilers png:./mochacfg.js
Or create a file 'test/mocha.opts' containing (better for your needs):
--compilers png:./mochacfg.js
With ./mochacfg.js:
require.extensions['.png'] = function(){ return null; }
This ignores png files (should be ok if you do nothing special with them).
If you want to do something with the image data:
var fs = require('fs');
require.extensions['.png'] = function(module, filepath) {
var src = fs.readFileSync(filepath).toString ('base64');
return module._compile('module.exports = "data:image/png;base64,' + src + '";');
}
Its quite late to answer this question but just for knowledge sharing purpose, I am answering another approach to do this.
Create a test-config.js file and use it while running the mocha test cases.
var jsdom = require('jsdom').jsdom;
process.env.NODE_ENV = 'test';
// -------------------------------
// Disable webpack-specific features for tests since
// Mocha doesn't know what to do with them.
['.css', '.scss', '.png', '.jpg'].forEach(ext => {
require.extensions[ext] = () => null;
});
and inside package.json use this test command to run the test cases
"test": "mocha ./test/test-setup.js './test/**/*.spec.js' --compilers js:babel-core/register",
I hope it helps someone.

How to write my own code generator of protobuf

Google protobuf is a nice IDL for RPC. But I want to know how to write my own code generator for protobuf.
The protoc compiler can output a protobuf-formatted description of the .proto file. That way most of the parsing has been done for you already, and you only need to generate the output you want.
The .proto schema for the .proto file description is here:
https://github.com/google/protobuf/blob/master/src/google/protobuf/descriptor.proto
As an additional step, you can make your generator runnable via an "-mygenerator-out=." option on protoc itself:
https://developers.google.com/protocol-buffers/docs/reference/other
Here is one (albeit a bit convoluted) example on how a code generator can be written in Python:
https://github.com/nanopb/nanopb/blob/master/generator/nanopb_generator.py
A protoc plugin is a binary that takes a protobuf message of type CodeGeneratorRequest and returns a response of type CodeGeneratorResponse to standard out.
The binary must be called protoc-gen-NAME and can be used by invoking the protoc command with:
protoc --plugin=./path/to/protoc-gen-NAME --NAME_out=./test/generated ./test.proto
Note specifically that names are important. This will not work, it will invoke the java generator:
protoc --plugin=./path/to/protoc-gen-NAME --java_out=./test/generated ./test.proto
This will not work, because the binary does not have the correct name:
protoc --plugin=./path/to/whatever-NAME --NAME_out=./test/generated ./test.proto
In order to process the incoming CodeGeneratorRequest and generate a valid response, your binary must itself be able to parse the protobuf message as per the protocol file plugin.proto from the protocolbuffers repository.
Historically this was difficult to do in a self-contained manner, but you can do this 'end-to-end' entirely in rust simply with the protobuf crate, like this trivial example demonstrates:
[dependencies]
protobuf="3.0.2"
use protobuf::plugin::{code_generator_response, CodeGeneratorRequest, CodeGeneratorResponse};
use protobuf::Message;
use std::io;
use std::io::{BufReader, Read, Write};
fn main() {
// Read message from stdin
let mut reader = BufReader::new(io::stdin());
let mut incoming_request = Vec::new();
reader.read_to_end(&mut incoming_request).unwrap();
// Parse as a request
let req = CodeGeneratorRequest::parse_from_bytes(&incoming_request).unwrap();
// Generate the content for each output file
let mut response = CodeGeneratorResponse::new();
for proto_file in req.proto_file.iter() {
let mut output = String::new();
output.push_str(&format!("// from file: {:?}\n", &proto_file.name));
output.push_str(&format!("// package: {:?}\n", &proto_file.package));
for message in proto_file.message_type.iter() {
output.push_str(&format!("\nmessage: {:?}\n", &message.name));
for field in message.field.iter() {
output.push_str(&format!(
"- {:?} {:?} {:?}\n",
field.type_,
field.type_name,
field.name(),
));
}
}
// Add it to the response
let mut output_file = code_generator_response::File::new();
output_file.content = Some(output);
output_file.name = Some(format!("{:?}/out.txt", &proto_file.name.as_ref().unwrap()));
response.file.push(output_file);
}
// Serialize the response to binary message and return it
let out_bytes: Vec<u8> = response.write_to_bytes().unwrap();
io::stdout().write_all(&out_bytes).unwrap();
}
Obviously this trivial example doesn't generate code, just text files, but it shows the basic process. You should also iterate over service and deal with all the additional properties on each type.
What this basically gives you is an AST matching the .proto files; the codegen side of it can be done however you like.
Helpful hints:
Do not log to stdout in your plugin, eg. for debugging. The only permitted output to stdout is a protobuf format CodeGeneratorResponse message.
The plugin does not write files, the protoc command does that; it should generate content and then return an array of files, along with content and metadata.
For more information on plugins, carefully read the plugin.proto file linked above; it has extensive details.

Resources