Commit 17bbdbd8 authored by harrylee's avatar harrylee

add fisco-client

parents
FROM golang:1.14.2 as builder
RUN mkdir -p /go/src/github.com/meshplus/pier-client-ethereum
WORKDIR /go/src/github.com/meshplus/pier-client-ethereum
# Cache dependencies
COPY . .
RUN mv build/pier ../pier
# Build real binaries
RUN go env -w GOPROXY=https://goproxy.cn,direct
RUN go get -u github.com/gobuffalo/packr/packr
RUN cd ../pier && make install
RUN cd ../pier-client-ethereum && \
make eth && \
cp build/eth-client.so /go/bin/eth-client.so
# Final image
FROM frolvlad/alpine-glibc
WORKDIR /root
# Copy over binaries from the builder
COPY --from=builder /go/bin/pier /usr/local/bin
COPY ./build/pier/build/libwasmer.so /lib
ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib
RUN ["pier", "init"]
RUN mkdir -p /root/.pier/plugins
COPY --from=builder /go/bin/*.so /root/.pier/plugins/
COPY config/validating.wasm /root/.pier/validating.wasm
COPY scripts/docker_entrypoint.sh /root/docker_entrypoint.sh
RUN chmod +x /root/docker_entrypoint.sh
COPY config /root/.pier/ether
COPY config/pier.toml /root/.pier/pier.toml
ENV APPCHAIN_NAME=ether
EXPOSE 44555 44544
ENTRYPOINT ["/root/docker_entrypoint.sh", "$APPCHAIN_NAME"]
\ No newline at end of file
SHELL := /bin/bash
CURRENT_PATH = $(shell pwd)
DISTRO = $(shell uname)
CURRENT_TAG =$(shell git describe --abbrev=0 --tags)
GO = GO111MODULE=on go
ifeq (docker,$(firstword $(MAKECMDGOALS)))
DOCKER_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
$(eval $(DOCKER_ARGS):;@:)
endif
help: Makefile
@echo "Choose a command run:"
@sed -n 's/^##//p' $< | column -t -s ':' | sed -e 's/^/ /'
## make fisco: build fisco client plugin
fisco:
@packr
mkdir -p build
$(GO) build -o build/fisco-client ./*.go
docker:
mkdir -p build
cd build && rm -rf sidecar && git clone https://gitlab.33.cn/link33/sidecar.git && cd sidecar && git checkout $(DOCKER_ARGS)
cd ${CURRENT_PATH}
docker build -t sidecar/sidecar-fisco .
release-binary:
mkdir -p build
$(GO) build -o build/fisco-client-${CURRENT_TAG}-${DISTRO} ./*.go
## make linter: Run golanci-lint
linter:
golangci-lint run -E goimports --skip-dirs-use-default -D staticcheck
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
package main
import (
"bytes"
"fmt"
"log"
"os"
"strings"
"github.com/spf13/viper"
)
// Config contains configuration items for sdk
type Config struct {
IsHTTP bool
ChainID int64
CAFile string
Key string
Cert string
IsSMCrypto bool
PrivateKey []byte
GroupID int
NodeURL string
ContractAddress string
Name string
TimeoutHeight int64
}
// ParseConfigFile parses the configuration from toml config file
func ParseConfigFile(cfgFile string) ([]Config, error) {
file, err := os.Open(cfgFile)
if err != nil {
return nil, fmt.Errorf("open file failed, err: %v", err)
}
defer func() {
err = file.Close()
if err != nil {
log.Fatalf("close file failed, err: %v", err)
}
}()
fileInfo, err := file.Stat()
if err != nil {
return nil, fmt.Errorf("file is not found, err: %v", err)
}
fileSize := fileInfo.Size()
buffer := make([]byte, fileSize)
_, err = file.Read(buffer)
if err != nil {
return nil, fmt.Errorf("read file failed, err: %v", err)
}
return ParseConfig(buffer)
}
// ParseConfig parses the configuration from []byte
func ParseConfig(buffer []byte) ([]Config, error) {
viper.SetConfigType("toml")
err := viper.ReadConfig(bytes.NewBuffer(buffer))
if err != nil {
return nil, fmt.Errorf("viper .ReadConfig failed, err: %v", err)
}
config := new(Config)
var configs []Config
viper.SetDefault("SMCrypto", false)
viper.SetDefault("Network.Type", "rpc")
viper.SetDefault("Network.CAFile", "ca.crt")
viper.SetDefault("Network.Key", "sdk.key")
viper.SetDefault("Network.Cert", "sdk.crt")
if viper.IsSet("Chain") {
if viper.IsSet("Chain.ChainID") {
config.ChainID = int64(viper.GetInt("Chain.ChainID"))
} else {
return nil, fmt.Errorf("Chain.ChainID has not been set")
}
if viper.IsSet("Chain.SMCrypto") {
config.IsSMCrypto = viper.GetBool("Chain.SMCrypto")
} else {
return nil, fmt.Errorf("SMCrypto has not been set")
}
} else {
return nil, fmt.Errorf("chain has not been set")
}
if viper.IsSet("Account") {
accountKeyFile := viper.GetString("Account.KeyFile")
keyBytes, curve, err := LoadECPrivateKeyFromPEM(accountKeyFile)
if err != nil {
return nil, fmt.Errorf("parse private key failed, err: %v", err)
}
if config.IsSMCrypto && curve != sm2p256v1 {
return nil, fmt.Errorf("smcrypto must use sm2p256v1 private key, but found %s", curve)
}
if !config.IsSMCrypto && curve != secp256k1 {
return nil, fmt.Errorf("must use secp256k1 private key, but found %s", curve)
}
config.PrivateKey = keyBytes
} else {
return nil, fmt.Errorf("network has not been set")
}
if viper.IsSet("Network") {
connectionType := viper.GetString("Network.Type")
if strings.EqualFold(connectionType, "rpc") {
config.IsHTTP = true
} else if strings.EqualFold(connectionType, "channel") {
config.IsHTTP = false
} else {
fmt.Printf("Network.Type %s is not supported, use channel", connectionType)
}
config.CAFile = viper.GetString("Network.CAFile")
config.Key = viper.GetString("Network.Key")
config.Cert = viper.GetString("Network.Cert")
var connections []struct {
GroupID int
NodeURL string
}
if viper.IsSet("Network.Connection") {
err := viper.UnmarshalKey("Network.Connection", &connections)
if err != nil {
return nil, fmt.Errorf("parse Network.Connection failed. err: %v", err)
}
for i := range connections {
configs = append(configs, *config)
configs[i].GroupID = connections[i].GroupID
configs[i].NodeURL = connections[i].NodeURL
}
} else {
return nil, fmt.Errorf("Network.Connection has not been set")
}
} else {
return nil, fmt.Errorf("network has not been set")
}
return configs, nil
}
// ParseConfigOptions parses from arguments
func ParseConfigOptions(caFile string, key string, cert, keyFile string, groupId int, ipPort string, isHttp bool, chainId int64, isSMCrypto bool) (*Config, error) {
config := Config{
IsHTTP: isHttp,
ChainID: chainId,
CAFile: caFile,
Key: key,
Cert: cert,
IsSMCrypto: isSMCrypto,
GroupID: groupId,
NodeURL: ipPort,
}
keyBytes, curve, err := LoadECPrivateKeyFromPEM(keyFile)
if err != nil {
return nil, fmt.Errorf("parse private key failed, err: %v", err)
}
if config.IsSMCrypto && curve != sm2p256v1 {
return nil, fmt.Errorf("smcrypto must use sm2p256v1 private key, but found %s", curve)
}
if !config.IsSMCrypto && curve != secp256k1 {
return nil, fmt.Errorf("must use secp256k1 private key, but found %s", curve)
}
config.PrivateKey = keyBytes
return &config, nil
}
{"address":"20f7fac801c5fc3f7e20cfbadaa1cdb33d818fa3","crypto":{"cipher":"aes-128-ctr","ciphertext":"8b60c0de32b4f06cc14932cdff70b3c01ecc21c25fcbfd0ad582f2bd19af7c30","cipherparams":{"iv":"29738398b8a2df14f74a81a4b547e3f6"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"2a26869c26b03202cc3e7b136742ac3c1793675912aa33a8adab1b15749b0dcd"},"mac":"0a4a5234df68e7fe014e6c09c1c6de36c3be08081f713d39512bdf82c9a6500c"},"id":"1f4f2381-aff1-40e0-9819-6c93f0645a6b","version":3}
\ No newline at end of file
[
{
"constant": false,
"inputs": [
{
"name": "destChainServiceID",
"type": "string"
},
{
"name": "key",
"type": "string"
}
],
"name": "get",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "key",
"type": "string"
}
],
"name": "interchainGet",
"outputs": [
{
"name": "",
"type": "bool"
},
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "key",
"type": "string"
},
{
"name": "value",
"type": "string"
}
],
"name": "interchainSet",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "key",
"type": "string"
}
],
"name": "getData",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "key",
"type": "string"
},
{
"name": "value",
"type": "string"
}
],
"name": "set",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
}
]
\ No newline at end of file
0x000f1a7a08ccc48e5d30f80850cf1cf283aa3abd,0xe93b92f1da08f925bdee44e91e7768380ae83307,0xb18c8575e3284e79b92100025a31378feb8100d6,0x856E2B9A5FA82FD1B031D1FF6863864DBAC7995D
\ No newline at end of file
[ether]
addr = "ws://host.docker.internal:8546"
name = "ether"
contract_address = "0xD3880ea40670eD51C3e3C0ea089fDbDc9e3FBBb4"
key_path = "account.key"
password = "password"
min_confirm = 15
timeout_height = 100
\ No newline at end of file
package config
import (
"crypto/x509/pkix"
"encoding/asn1"
"encoding/pem"
"errors"
"fmt"
"io/ioutil"
"math/big"
)
const (
secp256k1 = "secp256k1"
sm2p256v1 = "sm2p256v1"
)
var (
// oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33}
// oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7}
// oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34}
// oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35}
oidNamedCurveSecp256k1 = asn1.ObjectIdentifier{1, 3, 132, 0, 10}
oidNamedCurveSm2p256v1 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 301}
)
// LoadECPrivateKeyFromPEM reads file, divides into key and certificates
func LoadECPrivateKeyFromPEM(path string) ([]byte, string, error) {
raw, err := ioutil.ReadFile(path)
if err != nil {
return nil, "", err
}
block, _ := pem.Decode(raw)
if block == nil {
return nil, "", fmt.Errorf("Failure reading pem from \"%s\": %s", path, err)
}
if block.Type != "PRIVATE KEY" {
return nil, "", fmt.Errorf("Failure reading private key from \"%s\": %s", path, err)
}
ecPirvateKey, curveName, err := parsePKCS8ECPrivateKey(block.Bytes)
if err != nil {
return nil, "", fmt.Errorf("Failure reading private key from \"%s\": %s", path, err)
}
return ecPirvateKey, curveName, nil
}
// LoadECPublicKeyFromPEM reads file, divides into key and certificates
func LoadECPublicKeyFromPEM(path string) ([]byte, string, error) {
raw, err := ioutil.ReadFile(path)
if err != nil {
return nil, "", err
}
block, _ := pem.Decode(raw)
if block == nil {
return nil, "", fmt.Errorf("Failure reading pem from \"%s\": %s", path, err)
}
if block.Type != "PUBLIC KEY" {
return nil, "", fmt.Errorf("Failure reading private key from \"%s\": %s", path, err)
}
return parsePKIXPublicKey(block.Bytes)
}
// parseECPrivateKey is a copy of x509.ParseECPrivateKey, supported secp256k1 and sm2p256v1
func parsePKCS8ECPrivateKey(der []byte) (keyHex []byte, curveName string, err error) {
oidPublicKeyECDSA := asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}
// AlgorithmIdentifier represents the ASN.1 structure of the same name. See RFC
// 5280, section 4.1.1.2.
type AlgorithmIdentifier struct {
Algorithm asn1.ObjectIdentifier
Parameters asn1.RawValue `asn1:"optional"`
}
var pkcs8 struct {
Version int
Algo AlgorithmIdentifier
PrivateKey []byte
// optional attributes omitted.
}
var privKey struct {
Version int
PrivateKey []byte
NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"`
PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"`
}
if _, err := asn1.Unmarshal(der, &pkcs8); err != nil {
return nil, "", errors.New("x509: failed to parse EC private key embedded in PKCS#8: " + err.Error())
}
if !pkcs8.Algo.Algorithm.Equal(oidPublicKeyECDSA) {
return nil, "", fmt.Errorf("x509: PKCS#8 wrapping contained private key with unknown algorithm: %v", pkcs8.Algo.Algorithm)
}
bytes := pkcs8.Algo.Parameters.FullBytes
namedCurveOID := new(asn1.ObjectIdentifier)
if _, err := asn1.Unmarshal(bytes, namedCurveOID); err != nil {
namedCurveOID = nil
return nil, "", fmt.Errorf("parse namedCurveOID failed")
}
if _, err := asn1.Unmarshal(pkcs8.PrivateKey, &privKey); err != nil {
return nil, "", errors.New("x509: failed to parse EC private key: " + err.Error())
}
var curveOrder *big.Int
switch {
case namedCurveOID.Equal(oidNamedCurveSecp256k1):
curveName = "secp256k1"
curveOrder, _ = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16)
case namedCurveOID.Equal(oidNamedCurveSm2p256v1):
curveName = "sm2p256v1"
curveOrder, _ = new(big.Int).SetString("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", 16)
default:
return nil, "", fmt.Errorf("unknown namedCurveOID:%+v", namedCurveOID)
}
k := new(big.Int).SetBytes(privKey.PrivateKey)
if k.Cmp(curveOrder) >= 0 {
return nil, "", errors.New("x509: invalid elliptic curve private key value")
}
return privKey.PrivateKey, curveName, nil
}
// parsePKIXPublicKey is a copy of x509.ParsePKIXPublicKey, supported secp256k1 and sm2p256v1
func parsePKIXPublicKey(derBytes []byte) (pub []byte, curveName string, err error) {
type publicKeyInfo struct {
Raw asn1.RawContent
Algorithm pkix.AlgorithmIdentifier
PublicKey asn1.BitString
}
var pki publicKeyInfo
if rest, err := asn1.Unmarshal(derBytes, &pki); err != nil {
return nil, "", err
} else if len(rest) != 0 {
return nil, "", errors.New("x509: trailing data after ASN.1 of public-key")
}
oidPublicKeyECDSA := asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}
if !oidPublicKeyECDSA.Equal(oidPublicKeyECDSA) {
return nil, "", errors.New("x509: unsupported public key algorithm")
}
asn1Data := pki.PublicKey.RightAlign()
paramsData := pki.Algorithm.Parameters.FullBytes
namedCurveOID := new(asn1.ObjectIdentifier)
rest, err := asn1.Unmarshal(paramsData, namedCurveOID)
if err != nil {
return nil, "", errors.New("x509: failed to parse ECDSA parameters as named curve")
}
if len(rest) != 0 {
return nil, "", errors.New("x509: trailing data after ECDSA parameters")
}
switch {
case namedCurveOID.Equal(oidNamedCurveSecp256k1):
curveName = "secp256k1"
case namedCurveOID.Equal(oidNamedCurveSm2p256v1):
curveName = "sm2p256v1"
default:
return nil, "", fmt.Errorf("unknown namedCurveOID:%+v", namedCurveOID)
}
byteLen := 32
if len(asn1Data) != 1+2*byteLen {
return nil, curveName, nil
}
if asn1Data[0] != 4 { // uncompressed form
return nil, curveName, nil
}
return asn1Data, curveName, nil
}
\ No newline at end of file
title = "Pier"
[port]
http = 44544
pprof = 44555
[log]
level = "debug"
dir = "logs"
filename = "pier.log"
report_caller = false
[mode]
type = "relay" # relay or direct
[mode.relay]
addr = "host.docker.internal:60011"
quorum = 2
validators = [
"0x000f1a7a08ccc48e5d30f80850cf1cf283aa3abd",
"0xe93b92f1da08f925bdee44e91e7768380ae83307",
"0xb18c8575e3284e79b92100025a31378feb8100d6",
"0x856E2B9A5FA82FD1B031D1FF6863864DBAC7995D",
]
[mode.direct]
peers = [
#"/ip4/host.docker.internal/tcp/4002/p2p/Qmf4fn6sT3yLh3uqJnJ453yAhzpccbCQ75XfnBURTD3NoR",
"/ip4/host.docker.internal/tcp/4003/p2p/QmS78YUNXbxjaKivSygyDkxjZXedYy4TF6vfAJRPMRYdZ8",
"/ip4/host.docker.internal/tcp/4004/p2p/QmZpeCcBQBaurf8SUEvxjRY1nLYAHHUzqWLEXd4uoiuE9K"
]
[appchain]
id = "ethchain"
plugin = "eth-client.so"
config = "ether"
[
{
"constant": false,
"inputs": [
{
"name": "sender",
"type": "string"
},
{
"name": "receiver",
"type": "string"
},
{
"name": "val",
"type": "uint64"
},
{
"name": "isRollback",
"type": "bool"
}
],
"name": "interchainCharge",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "sender",
"type": "string"
},
{
"name": "val",
"type": "uint64"
}
],
"name": "interchainRollback",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "id",
"type": "string"
},
{
"name": "amount",
"type": "uint64"
}
],
"name": "setBalance",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "destContractDID",
"type": "string"
},
{
"name": "sender",
"type": "string"
},
{
"name": "receiver",
"type": "string"
},
{
"name": "amount",
"type": "string"
}
],
"name": "transfer",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "id",
"type": "string"
}
],
"name": "getBalance",
"outputs": [
{
"name": "",
"type": "uint64"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "self",
"type": "string"
}
],
"name": "parseInt",
"outputs": [
{
"name": "_ret",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
}
]
package main
import (
"fmt"
"gitlab.33.cn/link33/sidecar-client-fisco/broker"
)
func (c *Client) StartConsumer() error {
loop := func(interchainCh chan *broker.BrokerThrowInterchainEvent, receiptCh chan *broker.BrokerThrowReceiptEvent) {
for {
select {
case interchainEv := <-interchainCh:
ibtp, err := c.Convert2IBTP(interchainEv, int64(c.config.TimeoutHeight))
if err != nil {
logger.Warn("convert to IBTP", "src", interchainEv.SrcFullID, "dst", interchainEv.DstFullID, "idx", interchainEv.Index, "err", err.Error())
continue
}
c.eventC <- ibtp
case receiptEv := <-receiptCh:
ibtp, err := c.Convert2Receipt(receiptEv)
if err != nil {
logger.Warn("convert to IBTP", "src", receiptEv.SrcFullID, "dst", receiptEv.DstFullID, "idx", receiptEv.Index, "err", err.Error())
continue
}
c.eventC <- ibtp
case <-c.ctx.Done():
return
}
}
}
interchainCh := make(chan *broker.BrokerThrowInterchainEvent, 1024)
receiptCh := make(chan *broker.BrokerThrowReceiptEvent, 1024)
_, err := c.session.Contract.WatchThrowInterchainEvent(nil, interchainCh)
if err != nil {
return fmt.Errorf("watch event: %s", err)
}
_, err = c.session.Contract.WatchThrowReceiptEvent(nil, receiptCh)
if err != nil {
return fmt.Errorf("watch event: %s", err)
}
go loop(interchainCh, receiptCh)
logger.Info("Consumer started")
return nil
}
This diff is collapsed.
package main
import (
"bytes"
"gitlab.33.cn/link33/sidecar-client-fisco/broker"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"gitlab.33.cn/link33/sidecar/model/pb"
)
func (c *Client) Convert2IBTP(ev *broker.BrokerThrowInterchainEvent, timeoutHeight int64) (*pb.IBTP, error) {
fullEv, encrypt, err := c.fillInterchainEvent(ev)
if err != nil {
return nil, err
}
pd, err := encodePayload(fullEv, encrypt)
if err != nil {
return nil, err
}
return &pb.IBTP{
From: ev.SrcFullID,
To: ev.DstFullID,
Nonce: ev.Index,
Type: pb.IBTP_INTERCHAIN,
//TimeoutHeight: timeoutHeight,
Proof: []byte("1"),
Payload: pd,
}, nil
}
func (c *Client) Convert2Receipt(ev *broker.BrokerThrowReceiptEvent) (*pb.IBTP, error) {
fullEv, encrypt, err := c.fillReceiptEvent(ev)
if err != nil {
return nil, err
}
return generateReceipt(fullEv.SrcFullID, fullEv.DstFullID, fullEv.Index, fullEv.Result, fullEv.Typ, encrypt)
}
func encodePayload(ev *broker.BrokerThrowInterchainEvent, encrypt bool) ([]byte, error) {
var args [][]byte
for _, arg := range ev.Args {
args = append(args, []byte(arg))
}
content := &pb.Content{
Func: ev.Func,
Args: args,
}
data, err := content.Marshal()
if err != nil {
return nil, err
}
ibtppd := &pb.Payload{
Encrypted: encrypt,
Content: data,
//Hash: ev.Hash[:],
}
return ibtppd.Marshal()
}
func (c *Client) fillInterchainEvent(ev *broker.BrokerThrowInterchainEvent) (*broker.BrokerThrowInterchainEvent, bool, error) {
if ev.Func == "" {
fun, args, encrypt, err := c.session.GetOutMessage(genServicePair(ev.SrcFullID, ev.DstFullID), ev.Index)
if err != nil {
return nil, false, err
}
ev.Func = fun
ev.Args = args
emptyHash := common.Hash{}
if bytes.Equal(ev.Hash[:], emptyHash[:]) {
var data []byte
data = append(data, []byte(fun)...)
for _, arg := range args {
data = append(data, []byte(arg)...)
}
ev.Hash = common.BytesToHash(crypto.Keccak256(data))
}
return ev, encrypt, nil
}
return ev, false, nil
}
func (c *Client) fillReceiptEvent(ev *broker.BrokerThrowReceiptEvent) (*broker.BrokerThrowReceiptEvent, bool, error) {
if ev.Result == nil {
result, typ, encrypt, err := c.session.GetReceiptMessage(genServicePair(ev.SrcFullID, ev.DstFullID), ev.Index)
if err != nil {
return nil, false, err
}
ev.Result = result
ev.Typ = typ
emptyHash := common.Hash{}
if bytes.Equal(ev.Hash[:], emptyHash[:]) {
var packed []byte
for _, ele := range result {
packed = append(packed, ele...)
}
ev.Hash = common.BytesToHash(crypto.Keccak256(packed))
}
return ev, encrypt, nil
}
return ev, false, nil
}
This diff is collapsed.
pragma solidity >=0.5.6;
pragma experimental ABIEncoderV2;
contract DataSwapper {
mapping(string => string) dataM; // map for accounts
// change the address of Broker accordingly
address BrokerAddr;
// AccessControl
modifier onlyBroker {
require(msg.sender == BrokerAddr, "Invoker are not the Broker");
_;
}
constructor(address _brokerAddr) public {
BrokerAddr = _brokerAddr;
}
// contract for data exchange
function getData(string memory key) public view returns(string memory) {
return dataM[key];
}
function get(string memory destChainServiceID, string memory key) public {
bytes[] memory args = new bytes[](1);
args[0] = abi.encodePacked(key);
bytes[] memory argsCb = new bytes[](1);
argsCb[0] = abi.encodePacked(key);
Broker(BrokerAddr).emitInterchainEvent(destChainServiceID, "interchainGet", args, "interchainSet", argsCb, "", new bytes[](0), false);
}
function set(string memory key, string memory value) public {
dataM[key] = value;
}
function interchainSet(bytes[] memory args) public onlyBroker {
require(args.length == 2, "interchainSet args' length is not correct, expect 2");
string memory key = string(args[0]);
string memory value = string(args[1]);
set(key, value);
}
function interchainGet(bytes[] memory args, bool isRollback) public onlyBroker returns(bytes[] memory) {
require(args.length == 1, "interchainGet args' length is not correct, expect 1");
string memory key = string(args[0]);
bytes[] memory result = new bytes[](1);
result[0] = abi.encodePacked(dataM[key]);
return result;
}
}
abstract contract Broker {
function emitInterchainEvent(
string memory destFullServiceID,
string memory func,
bytes[] memory args,
string memory funcCb,
bytes[] memory argsCb,
string memory funcRb,
bytes[] memory argsRb,
bool isEncrypt) public virtual;
}
\ No newline at end of file
pragma solidity >=0.5.6;
pragma experimental ABIEncoderV2;
contract Transfer {
mapping(string => uint64) accountM; // map for accounts
// change the address of Broker accordingly
address BrokerAddr;
// AccessControl
modifier onlyBroker {
require(msg.sender == BrokerAddr, "Invoker are not the Broker");
_;
}
constructor(address _brokerAddr) public {
BrokerAddr = _brokerAddr;
}
// contract for asset
function transfer(string memory destChainServiceID, string memory sender, string memory receiver, uint64 amount) public {
require(accountM[sender] >= amount);
accountM[sender] -= amount;
bytes[] memory args = new bytes[](3);
args[0] = abi.encodePacked(sender);
args[1] =abi.encodePacked(receiver);
args[2] = abi.encodePacked(amount);
bytes[] memory argsRb = new bytes[](2);
argsRb[0] = abi.encodePacked(sender);
argsRb[1] = abi.encodePacked(amount);
Broker(BrokerAddr).emitInterchainEvent(destChainServiceID, "interchainCharge", args, "", new bytes[](0), "interchainRollback", argsRb, false);
}
function interchainRollback(bytes[] memory args) public onlyBroker {
require(args.length == 2, "interchainRollback args' length is not correct, expect 2");
string memory sender = string(args[0]);
uint64 amount = bytesToUint64(args[1]);
accountM[sender] += amount;
}
function interchainCharge(bytes[] memory args, bool isRollback) public onlyBroker returns (bytes[] memory) {
require(args.length == 3, "interchainCharge args' length is not correct, expect 3");
string memory receiver = string(args[1]);
uint64 amount = bytesToUint64(args[2]);
if (!isRollback) {
accountM[receiver] += amount;
} else {
accountM[receiver] -= amount;
}
return new bytes[](0);
}
function getBalance(string memory id) public view returns(uint64) {
return accountM[id];
}
function setBalance(string memory id, uint64 amount) public {
accountM[id] = amount;
}
function bytesToUint64(bytes memory b) public pure returns (uint64){
uint64 number;
for(uint i=0;i<b.length;i++){
number = uint64(number + uint8(b[i])*(2**(8*(b.length-(i+1)))));
}
return number;
}
}
abstract contract Broker {
function emitInterchainEvent(
string memory destFullServiceID,
string memory func,
bytes[] memory args,
string memory funcCb,
bytes[] memory argsCb,
string memory funcRb,
bytes[] memory argsRb,
bool isEncrypt) public virtual;
}
module gitlab.33.cn/link33/sidecar-client-fisco
go 1.13
require (
github.com/FISCO-BCOS/go-sdk v0.11.0
github.com/Rican7/retry v0.1.0
github.com/StackExchange/wmi v1.2.1 // indirect
github.com/ethereum/go-ethereum v1.10.7
github.com/fatih/color v1.12.0
github.com/gobuffalo/packd v1.0.0
github.com/gobuffalo/packr v1.30.1
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd
github.com/hashicorp/go-plugin v1.3.0
github.com/spf13/viper v1.7.1
github.com/urfave/cli v1.22.1
gitlab.33.cn/link33/sidecar v0.0.0-20220120062340-04eb4a2e720f
)
replace github.com/ethereum/go-ethereum => github.com/ethereum/go-ethereum v1.10.2
This source diff could not be displayed because it is too large. You can view the blob instead.
package main
import (
"io/ioutil"
"os"
"path/filepath"
"time"
"github.com/fatih/color"
"github.com/gobuffalo/packd"
"github.com/gobuffalo/packr"
"github.com/hashicorp/go-plugin"
"gitlab.33.cn/link33/sidecar/pkg/plugins"
"github.com/urfave/cli"
)
var initCMD = cli.Command{
Name: "init",
Usage: "Get appchain default configuration",
Flags: []cli.Flag{
cli.StringFlag{
Name: "target",
Usage: "Sepcify where to put the default configuration files",
Required: false,
},
},
Action: func(ctx *cli.Context) error {
target := ctx.String("target")
box := packr.NewBox("config")
if err := box.Walk(func(s string, file packd.File) error {
p := filepath.Join(target, s)
dir := filepath.Dir(p)
if _, err := os.Stat(dir); os.IsNotExist(err) {
err := os.MkdirAll(dir, 0755)
if err != nil {
return err
}
}
return ioutil.WriteFile(p, []byte(file.String()), 0644)
}); err != nil {
return err
}
return nil
},
}
var startCMD = cli.Command{
Name: "start",
Usage: "Start ethereum appchain plugin",
Action: func(ctx *cli.Context) error {
plugin.Serve(&plugin.ServeConfig{
HandshakeConfig: plugins.Handshake,
Plugins: map[string]plugin.Plugin{
plugins.PluginName: &plugins.AppchainGRPCPlugin{Impl: &Client{}},
},
Logger: logger,
GRPCServer: plugin.DefaultGRPCServer,
})
logger.Info("Plugin server down")
return nil
},
}
func main() {
app := cli.NewApp()
app.Name = "ethereum-plugin"
app.Usage = "Manipulate the ethereum blockchain"
app.Compiled = time.Now()
app.Commands = []cli.Command{
initCMD,
startCMD,
}
err := app.Run(os.Args)
if err != nil {
color.Red(err.Error())
os.Exit(-1)
}
}
package main
import (
"crypto/x509/pkix"
"encoding/asn1"
"encoding/pem"
"errors"
"fmt"
"io/ioutil"
"math/big"
)
const (
secp256k1 = "secp256k1"
sm2p256v1 = "sm2p256v1"
)
var (
// oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33}
// oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7}
// oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34}
// oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35}
oidNamedCurveSecp256k1 = asn1.ObjectIdentifier{1, 3, 132, 0, 10}
oidNamedCurveSm2p256v1 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 301}
)
// LoadECPrivateKeyFromPEM reads file, divides into key and certificates
func LoadECPrivateKeyFromPEM(path string) ([]byte, string, error) {
raw, err := ioutil.ReadFile(path)
if err != nil {
return nil, "", err
}
block, _ := pem.Decode(raw)
if block == nil {
return nil, "", fmt.Errorf("Failure reading pem from \"%s\": %s", path, err)
}
if block.Type != "PRIVATE KEY" {
return nil, "", fmt.Errorf("Failure reading private key from \"%s\": %s", path, err)
}
ecPirvateKey, curveName, err := parsePKCS8ECPrivateKey(block.Bytes)
if err != nil {
return nil, "", fmt.Errorf("Failure reading private key from \"%s\": %s", path, err)
}
return ecPirvateKey, curveName, nil
}
// LoadECPublicKeyFromPEM reads file, divides into key and certificates
func LoadECPublicKeyFromPEM(path string) ([]byte, string, error) {
raw, err := ioutil.ReadFile(path)
if err != nil {
return nil, "", err
}
block, _ := pem.Decode(raw)
if block == nil {
return nil, "", fmt.Errorf("Failure reading pem from \"%s\": %s", path, err)
}
if block.Type != "PUBLIC KEY" {
return nil, "", fmt.Errorf("Failure reading private key from \"%s\": %s", path, err)
}
return parsePKIXPublicKey(block.Bytes)
}
// parseECPrivateKey is a copy of x509.ParseECPrivateKey, supported secp256k1 and sm2p256v1
func parsePKCS8ECPrivateKey(der []byte) (keyHex []byte, curveName string, err error) {
oidPublicKeyECDSA := asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}
// AlgorithmIdentifier represents the ASN.1 structure of the same name. See RFC
// 5280, section 4.1.1.2.
type AlgorithmIdentifier struct {
Algorithm asn1.ObjectIdentifier
Parameters asn1.RawValue `asn1:"optional"`
}
var pkcs8 struct {
Version int
Algo AlgorithmIdentifier
PrivateKey []byte
// optional attributes omitted.
}
var privKey struct {
Version int
PrivateKey []byte
NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"`
PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"`
}
if _, err := asn1.Unmarshal(der, &pkcs8); err != nil {
return nil, "", errors.New("x509: failed to parse EC private key embedded in PKCS#8: " + err.Error())
}
if !pkcs8.Algo.Algorithm.Equal(oidPublicKeyECDSA) {
return nil, "", fmt.Errorf("x509: PKCS#8 wrapping contained private key with unknown algorithm: %v", pkcs8.Algo.Algorithm)
}
bytes := pkcs8.Algo.Parameters.FullBytes
namedCurveOID := new(asn1.ObjectIdentifier)
if _, err := asn1.Unmarshal(bytes, namedCurveOID); err != nil {
namedCurveOID = nil
return nil, "", fmt.Errorf("parse namedCurveOID failed")
}
if _, err := asn1.Unmarshal(pkcs8.PrivateKey, &privKey); err != nil {
return nil, "", errors.New("x509: failed to parse EC private key: " + err.Error())
}
var curveOrder *big.Int
switch {
case namedCurveOID.Equal(oidNamedCurveSecp256k1):
curveName = "secp256k1"
curveOrder, _ = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16)
case namedCurveOID.Equal(oidNamedCurveSm2p256v1):
curveName = "sm2p256v1"
curveOrder, _ = new(big.Int).SetString("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", 16)
default:
return nil, "", fmt.Errorf("unknown namedCurveOID:%+v", namedCurveOID)
}
k := new(big.Int).SetBytes(privKey.PrivateKey)
if k.Cmp(curveOrder) >= 0 {
return nil, "", errors.New("x509: invalid elliptic curve private key value")
}
return privKey.PrivateKey, curveName, nil
}
// parsePKIXPublicKey is a copy of x509.ParsePKIXPublicKey, supported secp256k1 and sm2p256v1
func parsePKIXPublicKey(derBytes []byte) (pub []byte, curveName string, err error) {
type publicKeyInfo struct {
Raw asn1.RawContent
Algorithm pkix.AlgorithmIdentifier
PublicKey asn1.BitString
}
var pki publicKeyInfo
if rest, err := asn1.Unmarshal(derBytes, &pki); err != nil {
return nil, "", err
} else if len(rest) != 0 {
return nil, "", errors.New("x509: trailing data after ASN.1 of public-key")
}
oidPublicKeyECDSA := asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}
if !oidPublicKeyECDSA.Equal(oidPublicKeyECDSA) {
return nil, "", errors.New("x509: unsupported public key algorithm")
}
asn1Data := pki.PublicKey.RightAlign()
paramsData := pki.Algorithm.Parameters.FullBytes
namedCurveOID := new(asn1.ObjectIdentifier)
rest, err := asn1.Unmarshal(paramsData, namedCurveOID)
if err != nil {
return nil, "", errors.New("x509: failed to parse ECDSA parameters as named curve")
}
if len(rest) != 0 {
return nil, "", errors.New("x509: trailing data after ECDSA parameters")
}
switch {
case namedCurveOID.Equal(oidNamedCurveSecp256k1):
curveName = "secp256k1"
case namedCurveOID.Equal(oidNamedCurveSm2p256v1):
curveName = "sm2p256v1"
default:
return nil, "", fmt.Errorf("unknown namedCurveOID:%+v", namedCurveOID)
}
byteLen := 32
if len(asn1Data) != 1+2*byteLen {
return nil, curveName, nil
}
if asn1Data[0] != 4 { // uncompressed form
return nil, curveName, nil
}
return asn1Data, curveName, nil
}
\ No newline at end of file
package main
import (
//"github.com/ethereum/go-ethereum/crypto"
"gitlab.33.cn/link33/sidecar/model/pb"
)
func (c *Client) generateCallback(original *pb.IBTP, data [][]byte, typ uint64) (result *pb.IBTP, err error) {
payload := &pb.Payload{}
if err := payload.Unmarshal(original.Payload); err != nil {
return nil, err
}
return generateReceipt(original.From, original.To, original.Nonce, data, typ, payload.Encrypted)
}
func generateReceipt(from, to string, idx uint64, data [][]byte, typ uint64, encrypt bool) (*pb.IBTP, error) {
result := &pb.Result{Data:data}
content, err := result.Marshal()
if err != nil {
return nil, err
}
var packed []byte
for _, ele := range data {
packed = append(packed, ele...)
}
payload := pb.Payload{
Encrypted: encrypt,
Content: content,
//Hash: crypto.Keccak256(packed),
}
pd, err := payload.Marshal()
if err != nil {
return nil, err
}
return &pb.IBTP{
From: from,
To: to,
Nonce: idx,
Type: pb.IBTP_Type(typ),
//TimeoutHeight: 0,
Proof: []byte("1"),
Payload: pd,
}, nil
}
// TODO
func unpackToBytesArray(data []byte) ([][]byte, error) {
return nil, nil
}
#!/usr/bin/env sh
set -e
APPCHAIN_NAME=$1
pier --repo=/root/.pier appchain register --name=${APPCHAIN_NAME} --type=ether --validators=/root/.pier/ether/ether.validators --desc="appchain for test" --version=1.9.3
pier --repo=/root/.pier rule deploy --path=/root/.pier/validating.wasm
pier --repo=/root/.pier start
\ No newline at end of file
Markdown is supported
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