Commit 7d479106 authored by duanjinfei's avatar duanjinfei

add moudle dependent

parent fd9bd792
Pipeline #573 canceled with stages
.idea
.vscode
build
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
package main
import (
"crypto/ecdsa"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"math/big"
)
type Account struct {
Address common.Address `json:"address"`
Private string `json:"private"`
Nonce uint64 `json:"nonce"`
PK *ecdsa.PrivateKey `json:"-"`
}
func (acc *Account) MakeInitTx(chainid *big.Int) *types.Transaction {
unit := new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)
txData := &types.LegacyTx{
Nonce: 0,
To: &acc.Address,
Value: new(big.Int).Mul(unit, big.NewInt(10)),
Gas: 300000,
GasPrice: big.NewInt(1000000000),
Data: nil,
}
tx, err := acc.SignTx(types.NewTx(txData), chainid)
if err != nil {
return nil
}
return tx
}
func (acc *Account) SignTx(tx *types.Transaction, chainid *big.Int) (*types.Transaction, error){
signedTx, err := types.SignTx(tx, types.NewEIP155Signer(chainid), acc.PK)
if err != nil {
return nil, err
}
return signedTx, nil
}
func CreateAccounts(count int) []*Account {
accs := make([]*Account, 0, count)
for i:=0; i < count; i++ {
pk,_ := crypto.GenerateKey()
addr := crypto.PubkeyToAddress(pk.PublicKey)
private := hexutil.Encode(crypto.FromECDSA(pk))
accs = append(accs, &Account{Address: addr, Private: private, PK: pk})
}
return accs
}
# Build MetaCryptor in a stock Go builder container
FROM golang:alpine as builder
RUN apk add --no-cache make git gcc musl-dev linux-headers
ADD . /code
ENV GO111MODULE off
RUN cd /code && make metacryptor
FROM alpine:latest
RUN echo "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.4/main/" > /etc/apk/repositories
RUN apk update \
&& apk upgrade \
&& apk add --no-cache bash \
bash-doc \
bash-completion \
&& rm -rf /var/cache/apk/* \
&& /bin/bash
RUN apk add --no-cache ca-certificates
COPY --from=builder /code/build/bin/metacryptor /usr/local/bin/
EXPOSE 38001
ENTRYPOINT ["metacryptor"]
MIT License
Copyright (c) 2022 CaduceusMetaverseProtocol
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
.PHONY: default metacryptor all clean fmt docker
GOBIN = $(shell pwd)/build/bin
GO ?= latest
GOFILES_NOVENDOR := $(shell go list -f "{{.Dir}}" ./...)
default: metacryptor
all: metacryptor metacryptor-ocl
metacryptor-ocl:
go build -tags opencl -o=${GOBIN}/$@
@echo "Done building."
metacryptor:
go build -o=${GOBIN}/$@
@echo "Done building."
clean:
rm -fr build/*
docker:
docker build -t cmpchain/metacryptor:latest .
# MetaCryptor
MetaCryptor is an independent module in CMPChain that supports the parallel encryption and decrypt which algorithm is ECDSA secp256k1.
package common
import (
metatypes "github.com/CaduceusMetaverseProtocol/MetaTypes/types"
ethcmn "github.com/ethereum/go-ethereum/common"
"math/big"
)
func FromBigInt(b *big.Int) *metatypes.BigInt {
n := metatypes.NewBigInt(0)
if b != nil {
n.Set(b)
}
return n
}
func ToBigInt(b *metatypes.BigInt) *big.Int {
return b.GetInt()
}
func ToHash(d []byte) *metatypes.Hash {
h := new(metatypes.Hash)
h.SetBytes(d)
return h
}
func ToEthAddress(d *metatypes.Address) *ethcmn.Address {
addr := new(ethcmn.Address)
if d != nil {
addr.SetBytes(d.Bytes())
}
return addr
}
func FromEthAddress(e *ethcmn.Address) *metatypes.Address {
addr := new(metatypes.Address)
addr.SetBytes(e.Bytes())
return addr
}
package common
import (
"encoding/hex"
"errors"
"github.com/CaduceusMetaverseProtocol/MetaCryptor/common/hexutil"
)
// FromHex returns the bytes represented by the hexadecimal string s.
// s may be prefixed with "0x".
func FromHex(s string) []byte {
if has0xPrefix(s) {
s = s[2:]
}
if len(s)%2 == 1 {
s = "0" + s
}
return Hex2Bytes(s)
}
// CopyBytes returns an exact copy of the provided bytes.
func CopyBytes(b []byte) (copiedBytes []byte) {
if b == nil {
return nil
}
copiedBytes = make([]byte, len(b))
copy(copiedBytes, b)
return
}
// has0xPrefix validates str begins with '0x' or '0X'.
func has0xPrefix(str string) bool {
return len(str) >= 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X')
}
// isHexCharacter returns bool of c being a valid hexadecimal.
func isHexCharacter(c byte) bool {
return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')
}
// isHex validates whether each byte is valid hexadecimal string.
func isHex(str string) bool {
if len(str)%2 != 0 {
return false
}
for _, c := range []byte(str) {
if !isHexCharacter(c) {
return false
}
}
return true
}
// Bytes2Hex returns the hexadecimal encoding of d.
func Bytes2Hex(d []byte) string {
return hex.EncodeToString(d)
}
// Hex2Bytes returns the bytes represented by the hexadecimal string str.
func Hex2Bytes(str string) []byte {
h, _ := hex.DecodeString(str)
return h
}
// Hex2BytesFixed returns bytes of a specified fixed length flen.
func Hex2BytesFixed(str string, flen int) []byte {
h, _ := hex.DecodeString(str)
if len(h) == flen {
return h
}
if len(h) > flen {
return h[len(h)-flen:]
}
hh := make([]byte, flen)
copy(hh[flen-len(h):flen], h)
return hh
}
// ParseHexOrString tries to hexdecode b, but if the prefix is missing, it instead just returns the raw bytes
func ParseHexOrString(str string) ([]byte, error) {
b, err := hexutil.Decode(str)
if errors.Is(err, hexutil.ErrMissingPrefix) {
return []byte(str), nil
}
return b, err
}
// RightPadBytes zero-pads slice to the right up to length l.
func RightPadBytes(slice []byte, l int) []byte {
if l <= len(slice) {
return slice
}
padded := make([]byte, l)
copy(padded, slice)
return padded
}
// LeftPadBytes zero-pads slice to the left up to length l.
func LeftPadBytes(slice []byte, l int) []byte {
if l <= len(slice) {
return slice
}
padded := make([]byte, l)
copy(padded[l-len(slice):], slice)
return padded
}
// TrimLeftZeroes returns a subslice of s without leading zeroes
func TrimLeftZeroes(s []byte) []byte {
idx := 0
for ; idx < len(s); idx++ {
if s[idx] != 0 {
break
}
}
return s[idx:]
}
// TrimRightZeroes returns a subslice of s without trailing zeroes
func TrimRightZeroes(s []byte) []byte {
idx := len(s)
for ; idx > 0; idx-- {
if s[idx-1] != 0 {
break
}
}
return s[:idx]
}
package hexutil
import (
"encoding/hex"
"fmt"
"math/big"
"strconv"
)
const uintBits = 32 << (uint64(^uint(0)) >> 63)
// Errors
var (
ErrEmptyString = &decError{"empty hex string"}
ErrSyntax = &decError{"invalid hex string"}
ErrMissingPrefix = &decError{"hex string without 0x prefix"}
ErrOddLength = &decError{"hex string of odd length"}
ErrEmptyNumber = &decError{"hex string \"0x\""}
ErrLeadingZero = &decError{"hex number with leading zero digits"}
ErrUint64Range = &decError{"hex number > 64 bits"}
ErrUintRange = &decError{fmt.Sprintf("hex number > %d bits", uintBits)}
ErrBig256Range = &decError{"hex number > 256 bits"}
)
type decError struct{ msg string }
func (err decError) Error() string { return err.msg }
// Decode decodes a hex string with 0x prefix.
func Decode(input string) ([]byte, error) {
if len(input) == 0 {
return nil, ErrEmptyString
}
if !has0xPrefix(input) {
return nil, ErrMissingPrefix
}
b, err := hex.DecodeString(input[2:])
if err != nil {
err = mapError(err)
}
return b, err
}
// MustDecode decodes a hex string with 0x prefix. It panics for invalid input.
func MustDecode(input string) []byte {
dec, err := Decode(input)
if err != nil {
panic(err)
}
return dec
}
// Encode encodes b as a hex string with 0x prefix.
func Encode(b []byte) string {
enc := make([]byte, len(b)*2+2)
copy(enc, "0x")
hex.Encode(enc[2:], b)
return string(enc)
}
// DecodeUint64 decodes a hex string with 0x prefix as a quantity.
func DecodeUint64(input string) (uint64, error) {
raw, err := checkNumber(input)
if err != nil {
return 0, err
}
dec, err := strconv.ParseUint(raw, 16, 64)
if err != nil {
err = mapError(err)
}
return dec, err
}
// MustDecodeUint64 decodes a hex string with 0x prefix as a quantity.
// It panics for invalid input.
func MustDecodeUint64(input string) uint64 {
dec, err := DecodeUint64(input)
if err != nil {
panic(err)
}
return dec
}
// EncodeUint64 encodes i as a hex string with 0x prefix.
func EncodeUint64(i uint64) string {
enc := make([]byte, 2, 10)
copy(enc, "0x")
return string(strconv.AppendUint(enc, i, 16))
}
var bigWordNibbles int
func init() {
// This is a weird way to compute the number of nibbles required for big.Word.
// The usual way would be to use constant arithmetic but go vet can't handle that.
b, _ := new(big.Int).SetString("FFFFFFFFFF", 16)
switch len(b.Bits()) {
case 1:
bigWordNibbles = 16
case 2:
bigWordNibbles = 8
default:
panic("weird big.Word size")
}
}
// DecodeBig decodes a hex string with 0x prefix as a quantity.
// Numbers larger than 256 bits are not accepted.
func DecodeBig(input string) (*big.Int, error) {
raw, err := checkNumber(input)
if err != nil {
return nil, err
}
if len(raw) > 64 {
return nil, ErrBig256Range
}
words := make([]big.Word, len(raw)/bigWordNibbles+1)
end := len(raw)
for i := range words {
start := end - bigWordNibbles
if start < 0 {
start = 0
}
for ri := start; ri < end; ri++ {
nib := decodeNibble(raw[ri])
if nib == badNibble {
return nil, ErrSyntax
}
words[i] *= 16
words[i] += big.Word(nib)
}
end = start
}
dec := new(big.Int).SetBits(words)
return dec, nil
}
// MustDecodeBig decodes a hex string with 0x prefix as a quantity.
// It panics for invalid input.
func MustDecodeBig(input string) *big.Int {
dec, err := DecodeBig(input)
if err != nil {
panic(err)
}
return dec
}
// EncodeBig encodes bigint as a hex string with 0x prefix.
func EncodeBig(bigint *big.Int) string {
if sign := bigint.Sign(); sign == 0 {
return "0x0"
} else if sign > 0 {
return "0x" + bigint.Text(16)
} else {
return "-0x" + bigint.Text(16)[1:]
}
}
func has0xPrefix(input string) bool {
return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X')
}
func checkNumber(input string) (raw string, err error) {
if len(input) == 0 {
return "", ErrEmptyString
}
if !has0xPrefix(input) {
return "", ErrMissingPrefix
}
input = input[2:]
if len(input) == 0 {
return "", ErrEmptyNumber
}
if len(input) > 1 && input[0] == '0' {
return "", ErrLeadingZero
}
return input, nil
}
const badNibble = ^uint64(0)
func decodeNibble(in byte) uint64 {
switch {
case in >= '0' && in <= '9':
return uint64(in - '0')
case in >= 'A' && in <= 'F':
return uint64(in - 'A' + 10)
case in >= 'a' && in <= 'f':
return uint64(in - 'a' + 10)
default:
return badNibble
}
}
func mapError(err error) error {
if err, ok := err.(*strconv.NumError); ok {
switch err.Err {
case strconv.ErrRange:
return ErrUint64Range
case strconv.ErrSyntax:
return ErrSyntax
}
}
if _, ok := err.(hex.InvalidByteError); ok {
return ErrSyntax
}
if err == hex.ErrLength {
return ErrOddLength
}
return err
}
package hexutil
import (
"encoding/hex"
"encoding/json"
"fmt"
"math/big"
"reflect"
"strconv"
)
var (
bytesT = reflect.TypeOf(Bytes(nil))
bigT = reflect.TypeOf((*Big)(nil))
uintT = reflect.TypeOf(Uint(0))
uint64T = reflect.TypeOf(Uint64(0))
)
// Bytes marshals/unmarshals as a JSON string with 0x prefix.
// The empty slice marshals as "0x".
type Bytes []byte
// MarshalText implements encoding.TextMarshaler
func (b Bytes) MarshalText() ([]byte, error) {
result := make([]byte, len(b)*2+2)
copy(result, `0x`)
hex.Encode(result[2:], b)
return result, nil
}
// UnmarshalJSON implements json.Unmarshaler.
func (b *Bytes) UnmarshalJSON(input []byte) error {
if !isString(input) {
return errNonString(bytesT)
}
return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bytesT)
}
// UnmarshalText implements encoding.TextUnmarshaler.
func (b *Bytes) UnmarshalText(input []byte) error {
raw, err := checkText(input, true)
if err != nil {
return err
}
dec := make([]byte, len(raw)/2)
if _, err = hex.Decode(dec, raw); err != nil {
err = mapError(err)
} else {
*b = dec
}
return err
}
// String returns the hex encoding of b.
func (b Bytes) String() string {
return Encode(b)
}
// ImplementsGraphQLType returns true if Bytes implements the specified GraphQL type.
func (b Bytes) ImplementsGraphQLType(name string) bool { return name == "Bytes" }
// UnmarshalGraphQL unmarshals the provided GraphQL query data.
func (b *Bytes) UnmarshalGraphQL(input interface{}) error {
var err error
switch input := input.(type) {
case string:
data, err := Decode(input)
if err != nil {
return err
}
*b = data
default:
err = fmt.Errorf("unexpected type %T for Bytes", input)
}
return err
}
// UnmarshalFixedJSON decodes the input as a string with 0x prefix. The length of out
// determines the required input length. This function is commonly used to implement the
// UnmarshalJSON method for fixed-size types.
func UnmarshalFixedJSON(typ reflect.Type, input, out []byte) error {
if !isString(input) {
return errNonString(typ)
}
return wrapTypeError(UnmarshalFixedText(typ.String(), input[1:len(input)-1], out), typ)
}
// UnmarshalFixedText decodes the input as a string with 0x prefix. The length of out
// determines the required input length. This function is commonly used to implement the
// UnmarshalText method for fixed-size types.
func UnmarshalFixedText(typname string, input, out []byte) error {
raw, err := checkText(input, true)
if err != nil {
return err
}
if len(raw)/2 != len(out) {
return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname)
}
// Pre-verify syntax before modifying out.
for _, b := range raw {
if decodeNibble(b) == badNibble {
return ErrSyntax
}
}
hex.Decode(out, raw)
return nil
}
// UnmarshalFixedUnprefixedText decodes the input as a string with optional 0x prefix. The
// length of out determines the required input length. This function is commonly used to
// implement the UnmarshalText method for fixed-size types.
func UnmarshalFixedUnprefixedText(typname string, input, out []byte) error {
raw, err := checkText(input, false)
if err != nil {
return err
}
if len(raw)/2 != len(out) {
return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname)
}
// Pre-verify syntax before modifying out.
for _, b := range raw {
if decodeNibble(b) == badNibble {
return ErrSyntax
}
}
hex.Decode(out, raw)
return nil
}
// Big marshals/unmarshals as a JSON string with 0x prefix.
// The zero value marshals as "0x0".
//
// Negative integers are not supported at this time. Attempting to marshal them will
// return an error. Values larger than 256bits are rejected by Unmarshal but will be
// marshaled without error.
type Big big.Int
// MarshalText implements encoding.TextMarshaler
func (b Big) MarshalText() ([]byte, error) {
return []byte(EncodeBig((*big.Int)(&b))), nil
}
// UnmarshalJSON implements json.Unmarshaler.
func (b *Big) UnmarshalJSON(input []byte) error {
if !isString(input) {
return errNonString(bigT)
}
return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bigT)
}
// UnmarshalText implements encoding.TextUnmarshaler
func (b *Big) UnmarshalText(input []byte) error {
raw, err := checkNumberText(input)
if err != nil {
return err
}
if len(raw) > 64 {
return ErrBig256Range
}
words := make([]big.Word, len(raw)/bigWordNibbles+1)
end := len(raw)
for i := range words {
start := end - bigWordNibbles
if start < 0 {
start = 0
}
for ri := start; ri < end; ri++ {
nib := decodeNibble(raw[ri])
if nib == badNibble {
return ErrSyntax
}
words[i] *= 16
words[i] += big.Word(nib)
}
end = start
}
var dec big.Int
dec.SetBits(words)
*b = (Big)(dec)
return nil
}
// ToInt converts b to a big.Int.
func (b *Big) ToInt() *big.Int {
return (*big.Int)(b)
}
// String returns the hex encoding of b.
func (b *Big) String() string {
return EncodeBig(b.ToInt())
}
// ImplementsGraphQLType returns true if Big implements the provided GraphQL type.
func (b Big) ImplementsGraphQLType(name string) bool { return name == "BigInt" }
// UnmarshalGraphQL unmarshals the provided GraphQL query data.
func (b *Big) UnmarshalGraphQL(input interface{}) error {
var err error
switch input := input.(type) {
case string:
return b.UnmarshalText([]byte(input))
case int32:
var num big.Int
num.SetInt64(int64(input))
*b = Big(num)
default:
err = fmt.Errorf("unexpected type %T for BigInt", input)
}
return err
}
// Uint64 marshals/unmarshals as a JSON string with 0x prefix.
// The zero value marshals as "0x0".
type Uint64 uint64
// MarshalText implements encoding.TextMarshaler.
func (b Uint64) MarshalText() ([]byte, error) {
buf := make([]byte, 2, 10)
copy(buf, `0x`)
buf = strconv.AppendUint(buf, uint64(b), 16)
return buf, nil
}
// UnmarshalJSON implements json.Unmarshaler.
func (b *Uint64) UnmarshalJSON(input []byte) error {
if !isString(input) {
return errNonString(uint64T)
}
return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), uint64T)
}
// UnmarshalText implements encoding.TextUnmarshaler
func (b *Uint64) UnmarshalText(input []byte) error {
raw, err := checkNumberText(input)
if err != nil {
return err
}
if len(raw) > 16 {
return ErrUint64Range
}
var dec uint64
for _, byte := range raw {
nib := decodeNibble(byte)
if nib == badNibble {
return ErrSyntax
}
dec *= 16
dec += nib
}
*b = Uint64(dec)
return nil
}
// String returns the hex encoding of b.
func (b Uint64) String() string {
return EncodeUint64(uint64(b))
}
// ImplementsGraphQLType returns true if Uint64 implements the provided GraphQL type.
func (b Uint64) ImplementsGraphQLType(name string) bool { return name == "Long" }
// UnmarshalGraphQL unmarshals the provided GraphQL query data.
func (b *Uint64) UnmarshalGraphQL(input interface{}) error {
var err error
switch input := input.(type) {
case string:
return b.UnmarshalText([]byte(input))
case int32:
*b = Uint64(input)
default:
err = fmt.Errorf("unexpected type %T for Long", input)
}
return err
}
// Uint marshals/unmarshals as a JSON string with 0x prefix.
// The zero value marshals as "0x0".
type Uint uint
// MarshalText implements encoding.TextMarshaler.
func (b Uint) MarshalText() ([]byte, error) {
return Uint64(b).MarshalText()
}
// UnmarshalJSON implements json.Unmarshaler.
func (b *Uint) UnmarshalJSON(input []byte) error {
if !isString(input) {
return errNonString(uintT)
}
return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), uintT)
}
// UnmarshalText implements encoding.TextUnmarshaler.
func (b *Uint) UnmarshalText(input []byte) error {
var u64 Uint64
err := u64.UnmarshalText(input)
if u64 > Uint64(^uint(0)) || err == ErrUint64Range {
return ErrUintRange
} else if err != nil {
return err
}
*b = Uint(u64)
return nil
}
// String returns the hex encoding of b.
func (b Uint) String() string {
return EncodeUint64(uint64(b))
}
func isString(input []byte) bool {
return len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"'
}
func bytesHave0xPrefix(input []byte) bool {
return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X')
}
func checkText(input []byte, wantPrefix bool) ([]byte, error) {
if len(input) == 0 {
return nil, nil // empty strings are allowed
}
if bytesHave0xPrefix(input) {
input = input[2:]
} else if wantPrefix {
return nil, ErrMissingPrefix
}
if len(input)%2 != 0 {
return nil, ErrOddLength
}
return input, nil
}
func checkNumberText(input []byte) (raw []byte, err error) {
if len(input) == 0 {
return nil, nil // empty strings are allowed
}
if !bytesHave0xPrefix(input) {
return nil, ErrMissingPrefix
}
input = input[2:]
if len(input) == 0 {
return nil, ErrEmptyNumber
}
if len(input) > 1 && input[0] == '0' {
return nil, ErrLeadingZero
}
return input, nil
}
func wrapTypeError(err error, typ reflect.Type) error {
if _, ok := err.(*decError); ok {
return &json.UnmarshalTypeError{Value: err.Error(), Type: typ}
}
return err
}
func errNonString(typ reflect.Type) error {
return &json.UnmarshalTypeError{Value: "non-string", Type: typ}
}
package log
import (
"context"
"github.com/lestrrat-go/file-rotatelogs"
"github.com/rifflock/lfshook"
"github.com/sirupsen/logrus"
"os"
"path"
"time"
)
var (
mlog = logrus.New()
)
type LogConfig struct {
Save uint `json:"save"`
Path string `json:"path"`
Level string `json:"level"`
}
func InitLog(logConfig LogConfig) {
mlog.Out = os.Stdout
var loglevel logrus.Level
err := loglevel.UnmarshalText([]byte(logConfig.Level))
if err != nil {
mlog.Panicf("set log level failed: %v", err)
}
mlog.SetLevel(loglevel)
mlog.Formatter = &logrus.TextFormatter{FullTimestamp: true, TimestampFormat: "2006-01-2 15:04:05.000"}
localFilesystemLogger(mlog, logConfig.Path, logConfig.Save)
}
func logWriter(logPath string, level string, save uint) *rotatelogs.RotateLogs {
logFullPath := path.Join(logPath, level)
logwriter, err := rotatelogs.New(
logFullPath+".%Y%m%d",
rotatelogs.WithLinkName(logFullPath),
rotatelogs.WithRotationCount(save),
rotatelogs.WithRotationTime(24*time.Hour),
)
if err != nil {
panic(err)
}
return logwriter
}
func localFilesystemLogger(log *logrus.Logger, logPath string, save uint) {
lfHook := lfshook.NewHook(lfshook.WriterMap{
logrus.DebugLevel: logWriter(logPath, "debug", save), // 为不同级别设置不同的输出目的
logrus.InfoLevel: logWriter(logPath, "info", save),
logrus.WarnLevel: logWriter(logPath, "warn", save),
logrus.ErrorLevel: logWriter(logPath, "error", save),
logrus.FatalLevel: logWriter(logPath, "fatal", save),
logrus.PanicLevel: logWriter(logPath, "panic", save),
}, &logrus.TextFormatter{FullTimestamp: true, TimestampFormat: "2006-01-2 15:04:05.000"})
log.AddHook(lfHook)
}
// WithField allocates a new entry and adds a field to it.
// Debug, Print, Info, Warn, Error, Fatal or Panic must be then applied to
// this new returned entry.
// If you want multiple fields, use `WithFields`.
func WithField(key string, value interface{}) *logrus.Entry {
return mlog.WithField(key, value)
}
// Adds a struct of fields to the log entry. All it does is call `WithField` for
// each `Field`.
func WithFields(fields logrus.Fields) *logrus.Entry {
return mlog.WithFields(fields)
}
// Add an error as single field to the log entry. All it does is call
// `WithError` for the given `error`.
func WithError(err error) *logrus.Entry {
return mlog.WithError(err)
}
// Add a context to the log entry.
func WithContext(ctx context.Context) *logrus.Entry {
return mlog.WithContext(ctx)
}
// Overrides the time of the log entry.
func WithTime(t time.Time) *logrus.Entry {
return mlog.WithTime(t)
}
func Logf(level logrus.Level, format string, args ...interface{}) {
mlog.Logf(level, format, args...)
}
func Tracef(format string, args ...interface{}) {
mlog.Tracef(format, args...)
}
func Debugf(format string, args ...interface{}) {
mlog.Debugf(format, args...)
}
func Infof(format string, args ...interface{}) {
mlog.Infof(format, args...)
}
func Printf(format string, args ...interface{}) {
mlog.Printf(format, args...)
}
func Warnf(format string, args ...interface{}) {
mlog.Warnf(format, args...)
}
func Warningf(format string, args ...interface{}) {
mlog.Warningf(format, args...)
}
func Errorf(format string, args ...interface{}) {
mlog.Errorf(format, args)
}
func Fatalf(format string, args ...interface{}) {
mlog.Fatalf(format, args...)
}
func Panicf(format string, args ...interface{}) {
mlog.Panicf(format, args...)
}
func Log(level logrus.Level, args ...interface{}) {
mlog.Log(level, args...)
}
func LogFn(level logrus.Level, fn logrus.LogFunction) {
mlog.LogFn(level, fn)
}
func Trace(args ...interface{}) {
mlog.Trace(args...)
}
func Debug(args ...interface{}) {
mlog.Debug(args...)
}
func Info(args ...interface{}) {
mlog.Info(args...)
}
func Print(args ...interface{}) {
mlog.Print(args...)
}
func Warn(args ...interface{}) {
mlog.Warn(args...)
}
func Warning(args ...interface{}) {
mlog.Warning(args...)
}
func Error(args ...interface{}) {
mlog.Error(args...)
}
func Fatal(args ...interface{}) {
mlog.Fatal(args...)
}
func Panic(args ...interface{}) {
mlog.Panic(args...)
}
func TraceFn(fn logrus.LogFunction) {
mlog.TraceFn(fn)
}
func DebugFn(fn logrus.LogFunction) {
mlog.DebugFn(fn)
}
func InfoFn(fn logrus.LogFunction) {
mlog.InfoFn(fn)
}
func PrintFn(fn logrus.LogFunction) {
mlog.PrintFn(fn)
}
func WarnFn(fn logrus.LogFunction) {
mlog.WarnFn(fn)
}
func WarningFn(fn logrus.LogFunction) {
mlog.WarningFn(fn)
}
func ErrorFn(fn logrus.LogFunction) {
mlog.ErrorFn(fn)
}
func FatalFn(fn logrus.LogFunction) {
mlog.FatalFn(fn)
}
func PanicFn(fn logrus.LogFunction) {
mlog.PanicFn(fn)
}
func Logln(level logrus.Level, args ...interface{}) {
mlog.Logln(level, args...)
}
func Traceln(args ...interface{}) {
mlog.Traceln(args...)
}
func Debugln(args ...interface{}) {
mlog.Debugln(args...)
}
func Infoln(args ...interface{}) {
mlog.Infoln(args...)
}
func Println(args ...interface{}) {
mlog.Println(args...)
}
func Warnln(args ...interface{}) {
mlog.Warnln(args...)
}
func Warningln(args ...interface{}) {
mlog.Warningln(args...)
}
func Errorln(args ...interface{}) {
mlog.Errorln(args...)
}
func Fatalln(args ...interface{}) {
mlog.Fatalln(args...)
}
func Panicln(args ...interface{}) {
mlog.Panicln(args...)
}
package crypto
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/sha256"
"errors"
"fmt"
"github.com/btcsuite/btcd/btcec"
"github.com/ethereum/go-ethereum/crypto"
"github.com/tjfoc/gmsm/sm2"
"math/big"
)
//
func RecoverPubkey(msg, signature []byte) ([]byte, error) {
return crypto.Ecrecover(msg, signature)
}
func RecoverableSign(msg, seckey []byte) ([]byte, error) {
if len(msg) != 32 {
return nil, fmt.Errorf("hash is required to be exactly 32 bytes (%d)", len(msg))
}
prv, _ := btcec.PrivKeyFromBytes(btcec.S256(), seckey)
sig, err := btcec.SignCompact(btcec.S256(), (*btcec.PrivateKey)(prv), msg, false)
if err != nil {
return nil, err
}
// Convert to Ethereum signature format with 'recovery id' v at the end.
v := sig[0] - 27
copy(sig, sig[1:])
sig[64] = v
return sig, nil
}
func Secp256k1Sign(msg, seckey []byte) ([]byte, error) {
priv, _ := btcec.PrivKeyFromBytes(btcec.S256(), seckey)
msghash := sha256.Sum256(msg)
sig, err := priv.Sign(msghash[:])
if err != nil {
return nil, err
}
rBytes := sig.R.Bytes()
sBytes := sig.S.Bytes()
sigBytes := make([]byte, 64)
// 0 pad the byte arrays from the left if they aren't big enough.
copy(sigBytes[32-len(rBytes):32], rBytes)
copy(sigBytes[64-len(sBytes):64], sBytes)
return sigBytes, nil
}
// warning: pubkey size is 64, not 65.
func Secp256k1Verify(msg, pubkey, sign []byte) (bool, error) {
var secp256k1halfN = new(big.Int).Rsh(btcec.S256().N, 1)
sig := &btcec.Signature{R: new(big.Int).SetBytes(sign[:32]), S: new(big.Int).SetBytes(sign[32:])}
key, err := btcec.ParsePubKey(pubkey, btcec.S256())
if err != nil {
return false, errors.New(fmt.Sprintf("parse to secp256k1 pubkey invalid pubkey:%s", err.Error()))
}
// Reject malleable signatures. libsecp256k1 does this check but btcec doesn't.
if sig.S.Cmp(secp256k1halfN) > 0 {
return false, nil
}
return sig.Verify(msg, key), nil
}
func parseToEcdsaP256PrivateKey(seckey []byte) (*ecdsa.PrivateKey, error) {
if len(seckey) != 32 {
return nil, errors.New("invalid seckey")
}
k := big.NewInt(0).SetBytes(seckey)
p256 := elliptic.P256()
priv := new(ecdsa.PrivateKey)
priv.PublicKey.Curve = p256
priv.D = k
priv.PublicKey.X, priv.PublicKey.Y = p256.ScalarBaseMult(k.Bytes())
return priv, nil
}
func parseToEcdsaP256PublicKey(pubkey []byte) (*ecdsa.PublicKey, error) {
if len(pubkey) != 64 {
return nil, errors.New("parse to ecdsap256 pubkey invalid pubkey")
}
pubk := new(ecdsa.PublicKey)
pubk.Curve = elliptic.P256()
pubk.X = big.NewInt(0).SetBytes(pubkey[:32])
pubk.Y = big.NewInt(0).SetBytes(pubkey[32:64])
return pubk, nil
}
func EcdsaP256Sign(msg, seckey []byte) ([]byte, error) {
privk, err := parseToEcdsaP256PrivateKey(seckey)
if err != nil {
return nil, err
}
// warning: ecdsa sign add random before msg
signature, err := privk.Sign(rand.Reader, msg, nil)
if err != nil {
return nil, err
}
r, s, err := sm2.SignDataToSignDigit(signature)
if err != nil {
return nil, err
}
sign := make([]byte, 64)
copy(sign[:32], r.Bytes())
copy(sign[32:], s.Bytes())
return sign, nil
}
func EcdsaP256Verify(msg []byte, pubkey []byte, sign []byte) (bool, error) {
public, err := parseToEcdsaP256PublicKey(pubkey)
if err != nil {
return false, err
}
r := big.NewInt(0).SetBytes(sign[:32])
s := big.NewInt(0).SetBytes(sign[32:64])
ret := ecdsa.Verify(public, msg, r, s)
return ret, nil
}
func parseToSM2PrivateKey(seckey []byte) (*sm2.PrivateKey, error) {
if len(seckey) != 32 {
return nil, errors.New("invalid seckey")
}
c := sm2.P256Sm2()
k := big.NewInt(0).SetBytes(seckey)
priv := new(sm2.PrivateKey)
priv.PublicKey.Curve = c
priv.D = k
priv.PublicKey.X, priv.PublicKey.Y = c.ScalarBaseMult(k.Bytes())
return priv, nil
}
func parseToSM2PublicKey(pubkey []byte) (*sm2.PublicKey, error) {
if len(pubkey) != 64 {
return nil, errors.New("parse to sm2 pubkey and invalid pubkey")
}
c := sm2.P256Sm2()
pubk := new(sm2.PublicKey)
pubk.Curve = c
pubk.X = big.NewInt(0).SetBytes(pubkey[:32])
pubk.Y = big.NewInt(0).SetBytes(pubkey[32:64])
return pubk, nil
}
func SM2Sign(msg, seckey []byte) ([]byte, error) {
priv, err := parseToSM2PrivateKey(seckey)
if err != nil {
return nil, err
}
signature, err := priv.Sign(nil, msg, nil)
if err != nil {
return nil, err
}
r, s, err := sm2.SignDataToSignDigit(signature)
if err != nil {
return nil, err
}
sign := make([]byte, 64)
copy(sign[:32], r.Bytes())
copy(sign[32:], s.Bytes())
return sign, nil
}
func SM2Verify(msg []byte, pubkey []byte, sign []byte) (bool, error) {
public, err := parseToSM2PublicKey(pubkey)
if err != nil {
return false, err
}
r := big.NewInt(0).SetBytes(sign[:32])
s := big.NewInt(0).SetBytes(sign[32:64])
signature, err := sm2.SignDigitToSignData(r, s)
if err != nil {
return false, err
}
ret := public.Verify(msg, signature)
return ret, nil
}
package crypto
import "bytes"
func BytesCombine(pBytes ...[]byte) []byte {
return bytes.Join(pBytes, []byte(""))
}
package crypto
import (
"golang.org/x/crypto/sha3"
"hash"
)
type KeccakState interface {
hash.Hash
Read([]byte) (int, error)
}
// NewKeccakState creates a new KeccakState
func NewKeccakState() KeccakState {
return sha3.NewLegacyKeccak256().(KeccakState)
}
// Keccak256 calculates and returns the Keccak256 hash of the input data.
func Keccak256(data ...[]byte) []byte {
b := make([]byte, 32)
d := NewKeccakState()
for _, b := range data {
d.Write(b)
}
d.Read(b)
return b
}
package crypto
import (
"github.com/CaduceusMetaverseProtocol/MetaCryptor/common"
basev1 "github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/base/v1"
"github.com/ethereum/go-ethereum/core/types"
"math/big"
)
func SignedHash(tx *basev1.MetaTxBase, chainid *big.Int) []byte {
txdata := &types.LegacyTx{
Nonce: tx.Nonce,
GasPrice: common.ToBigInt(tx.GasPrice),
Gas: tx.Gas,
To: common.ToEthAddress(tx.To),
Value: common.ToBigInt(tx.Value),
Data: tx.Data,
V: common.ToBigInt(tx.V),
R: common.ToBigInt(tx.R),
S: common.ToBigInt(tx.S),
}
ntx := types.NewTx(txdata)
signer := types.NewEIP155Signer(chainid)
return signer.Hash(ntx).Bytes()
}
module github.com/CaduceusMetaverseProtocol/MetaCryptor
go 1.18
require (
github.com/CaduceusMetaverseProtocol/MetaProtocol v0.0.1
github.com/btcsuite/btcd v0.21.0-beta
github.com/ethereum/go-ethereum v1.10.26
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
github.com/rakyll/statik v0.1.7
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5
github.com/sirupsen/logrus v1.9.0
github.com/tjfoc/gmsm v1.4.1
golang.org/x/crypto v0.5.0
google.golang.org/grpc v1.51.0
)
require (
github.com/CaduceusMetaverseProtocol/MetaTypes v1.0.0 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/jonboulle/clockwork v0.3.0 // indirect
github.com/lestrrat-go/strftime v1.0.6 // indirect
github.com/pkg/errors v0.9.1 // indirect
golang.org/x/net v0.5.0 // indirect
golang.org/x/sys v0.4.0 // indirect
golang.org/x/text v0.6.0 // indirect
google.golang.org/genproto v0.0.0-20221205194025-8222ab48f5fc // indirect
google.golang.org/protobuf v1.28.1 // indirect
)
replace github.com/CaduceusMetaverseProtocol/MetaProtocol => ../MetaProtocol-main
replace github.com/CaduceusMetaverseProtocol/MetaTypes => ../MetaTypes-main
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8=
github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
github.com/btcsuite/btcd v0.21.0-beta h1:At9hIZdJW0s9E/fAz28nrz6AmcNlSVucCH796ZteX1M=
github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94=
github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k=
github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts=
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I=
github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0=
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ethereum/go-ethereum v1.10.26 h1:i/7d9RBBwiXCEuyduBQzJw/mKmnvzsN14jqBmytw72s=
github.com/ethereum/go-ethereum v1.10.26/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jonboulle/clockwork v0.3.0 h1:9BSCMi8C+0qdApAp4auwX0RkLGUjs956h0EkuQymUhg=
github.com/jonboulle/clockwork v0.3.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8=
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is=
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4=
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA=
github.com/lestrrat-go/strftime v1.0.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205AhTIGQQ=
github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA=
github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ=
github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc=
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 h1:mZHayPoR0lNmnHyvtYjDeq0zlVHn9K/ZXoy17ylucdo=
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5/go.mod h1:GEXHk5HgEKCvEIIrSpFI3ozzG5xOKA2DVlEX/gGnewM=
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4=
github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df h1:5Pf6pFKu98ODmgnpvkJ3kFUOQGGLIzLIkbzUHp47618=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20221205194025-8222ab48f5fc h1:nUKKji0AarrQKh6XpFEpG3p1TNztxhe7C8TcUvDgXqw=
google.golang.org/genproto v0.0.0-20221205194025-8222ab48f5fc/go.mod h1:1dOng4TWOomJrDGhpXjfCD35wQC6jnC7HpRmOFRqEV0=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U=
google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
package main
import (
"context"
"fmt"
"github.com/CaduceusMetaverseProtocol/MetaCryptor/common"
"github.com/CaduceusMetaverseProtocol/MetaCryptor/common/log"
"github.com/CaduceusMetaverseProtocol/MetaCryptor/service"
"github.com/CaduceusMetaverseProtocol/MetaCryptor/xecc"
basetype "github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/base/v1"
metacrypter "github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/crypter/v1"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"math/big"
"net"
"time"
)
func test() {
time.Sleep(time.Second * 4)
client, err := grpc.Dial("127.0.0.1:38001", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Error("dial server failed", err)
}
accounts := CreateAccounts(1)
log.Info("account address is ", accounts[0].Address.String())
tx := accounts[0].MakeInitTx(big.NewInt(100))
crypterclient := metacrypter.NewCrypterServiceClient(client)
req := new(metacrypter.BatchRecoverTxRequest)
req.RawTx = make([]*basetype.MetaTxBase, 0)
v, r, s := tx.RawSignatureValues()
log.WithField("txhash", tx.Hash().String()).Info("txhash")
log.WithField("r", common.Bytes2Hex(r.Bytes())).Info("tx r")
log.WithField("s", common.Bytes2Hex(s.Bytes())).Info("tx s")
log.WithField("v", common.Bytes2Hex(v.Bytes())).Info("tx v")
rtx := &basetype.MetaTxBase{
TxHash: common.ToHash(tx.Hash().Bytes()),
TxType: 1,
ChainId: common.FromBigInt(big.NewInt(100)),
Gas: tx.Gas(),
GasPrice: common.FromBigInt(tx.GasPrice()),
Value: common.FromBigInt(tx.Value()),
Data: tx.Data(),
Nonce: tx.Nonce(),
To: common.FromEthAddress(tx.To()),
R: common.FromBigInt(r),
S: common.FromBigInt(s),
V: common.FromBigInt(v),
}
req.RawTx = append(req.RawTx, rtx)
res, err := crypterclient.BatchRecoverTx(context.Background(), req, grpc.EmptyCallOption{})
if err != nil {
log.Error("batch recover tx failed", err)
}
log.Info("recover got from ", res.RecoverdTx[0].From)
}
func main() {
xecc.XeccInstance()
lis, err := net.Listen("tcp", ":38001")
if err != nil {
fmt.Printf("failed to listen: %v", err)
return
}
s := grpc.NewServer()
service.RegisterCrypter(s)
go test()
err = s.Serve(lis)
if err != nil {
fmt.Printf("failed to serve: %v", err)
return
}
}
package service
import (
"context"
"encoding/hex"
"github.com/CaduceusMetaverseProtocol/MetaCryptor/common"
"github.com/CaduceusMetaverseProtocol/MetaCryptor/common/log"
metatypes "github.com/CaduceusMetaverseProtocol/MetaTypes/types"
"math/big"
"github.com/CaduceusMetaverseProtocol/MetaCryptor/crypto"
metacrypter "github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/crypter/v1"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
type CrypterServer struct {
metacrypter.UnimplementedCrypterServiceServer
}
func (*CrypterServer) BatchSign(ctx context.Context, req *metacrypter.BatchSignRequest) (*metacrypter.BatchSignResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method BatchSign not implemented")
}
func (*CrypterServer) BatchVerify(ctx context.Context, req *metacrypter.BatchVerifyRequest) (*metacrypter.BatchVerifyResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method BatchVerify not implemented")
}
func (*CrypterServer) BatchRecover(ctx context.Context, req *metacrypter.BatchRecoverRequest) (*metacrypter.BatchRecoverResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method BatchRecover not implemented")
}
func (*CrypterServer) BatchRecoverTx(ctx context.Context, req *metacrypter.BatchRecoverTxRequest) (*metacrypter.BatchRecoverTxResponse, error) {
//tasks := make([]*XTaskSecp256k1RPubkey, len(req.RawTx))
//big8 := big.NewInt(8)
log.Info("server get batch recover tx request")
froms := make([][]byte, len(req.RawTx))
for i, tx := range req.RawTx {
log.WithField("txhash", tx.TxHash.String()).Info("txhash")
log.WithField("r", tx.R.String()).Info("tx r")
log.WithField("s", tx.S.String()).Info("tx s")
log.WithField("v", tx.V.String()).Info("tx v")
log.WithField("chainid", tx.ChainId.String()).Info("tx chainid")
V := common.ToBigInt(tx.V)
chainid := common.ToBigInt(tx.ChainId)
chainIdMul := new(big.Int).Mul(chainid, big.NewInt(2))
v := new(big.Int).Sub(V, chainIdMul)
vb := byte(v.Uint64() - 35)
log.WithField("vb is ", vb).Info("vb")
signature := make([]byte, 65)
copy(signature[:32], common.LeftPadBytes(tx.R.Bytes(), 32))
copy(signature[32:64], common.LeftPadBytes(tx.S.Bytes(), 32))
signature[64] = vb
pubk, err := crypto.RecoverPubkey(common.LeftPadBytes(crypto.SignedHash(tx, chainid), 32), signature)
if err != nil {
log.Info("recover failed for tx", "index", i, "err", err)
} else {
froms[i] = common.CopyBytes(crypto.Keccak256(pubk[1:])[12:])
log.Info("recover address is ", hex.EncodeToString(froms[i]))
}
//task := &XTaskSecp256k1RPubkey{
// Msg: tx.TxHash.Hash,
// Rsig: crypto.BytesCombine(common.LeftPadBytes(tx.R.Data, 32), common.LeftPadBytes(tx.S.Data, 32), []byte{vb}),
//}
//tasks[i] = task
}
response := new(metacrypter.BatchRecoverTxResponse)
response.RecoverdTx = req.RawTx
//resps, err := xecc.XeccInstance().BatchSecp256k1RecoverPubkey(tasks)
//if err != nil {
// return response, err
//}
for i := 0; i < len(response.RecoverdTx); i++ {
a := metatypes.BytesToAddress(froms[i])
response.RecoverdTx[i].From = &a
}
return response, nil
}
func RegisterCrypter(server *grpc.Server) {
metacrypter.RegisterCrypterServiceServer(server, &CrypterServer{})
}
package xecc
import (
. "github.com/CaduceusMetaverseProtocol/MetaCryptor/xecc/types"
)
func (x *Xecc) BatchSecp256k1RecoverPubkey(tasks []*XTaskSecp256k1RPubkey) ([]*XTaskSecp256k1RPubkey, error) {
var eng Engine
eng = x.cpue
var tall = make([]XTask, len(tasks))
for i := 0; i < len(tasks); i++ {
tall[i] = tasks[i]
}
res, e := eng.ProcessBatch(tall)
var xs = make([]*XTaskSecp256k1RPubkey, 0)
for _, t := range res {
xs = append(xs, t.(*XTaskSecp256k1RPubkey))
}
return xs, e
}
func (x *Xecc) BatchSecp256k1RecoverableSign(tasks []*XTaskSecp256k1RSign) ([]*XTaskSecp256k1RSign, error) {
var eng Engine
eng = x.cpue
var tall = make([]XTask, len(tasks))
for i := 0; i < len(tasks); i++ {
tall[i] = tasks[i]
}
res, e := eng.ProcessBatch(tall)
var xs = make([]*XTaskSecp256k1RSign, 0)
for _, t := range res {
xs = append(xs, t.(*XTaskSecp256k1RSign))
}
return xs, e
}
func (x *Xecc) BatchSecp256k1Sign(tasks []*XTaskSecp256k1Sign) ([]*XTaskSecp256k1Sign, error) {
var eng Engine
eng = x.cpue
var tall = make([]XTask, len(tasks))
for i := 0; i < len(tasks); i++ {
tall[i] = tasks[i]
}
res, e := eng.ProcessBatch(tall)
var xs = make([]*XTaskSecp256k1Sign, 0)
for _, t := range res {
xs = append(xs, t.(*XTaskSecp256k1Sign))
}
return xs, e
}
func (x *Xecc) BatchSecp256k1Verify(tasks []*XTaskSecp256k1Verify) ([]*XTaskSecp256k1Verify, error) {
var eng Engine
eng = x.cpue
var tall = make([]XTask, len(tasks))
for i := 0; i < len(tasks); i++ {
tall[i] = tasks[i]
}
res, e := eng.ProcessBatch(tall)
var xs = make([]*XTaskSecp256k1Verify, 0)
for _, t := range res {
xs = append(xs, t.(*XTaskSecp256k1Verify))
}
return xs, e
}
func (x *Xecc) BatchEcdsaSign(tasks []*XTaskEcdsa256Sign) ([]*XTaskEcdsa256Sign, error) {
var eng Engine
eng = x.cpue
var tall = make([]XTask, len(tasks))
for i := 0; i < len(tasks); i++ {
tall[i] = tasks[i]
}
res, e := eng.ProcessBatch(tall)
var xs = make([]*XTaskEcdsa256Sign, 0)
for _, t := range res {
xs = append(xs, t.(*XTaskEcdsa256Sign))
}
return xs, e
}
func (x *Xecc) BatchEcdsaVerify(tasks []*XTaskEcdsa256Verify) ([]*XTaskEcdsa256Verify, error) {
var eng Engine
eng = x.cpue
var tall = make([]XTask, len(tasks))
for i := 0; i < len(tasks); i++ {
tall[i] = tasks[i]
}
res, e := eng.ProcessBatch(tall)
var xs = make([]*XTaskEcdsa256Verify, 0)
for _, t := range res {
xs = append(xs, t.(*XTaskEcdsa256Verify))
}
return xs, e
}
func (x *Xecc) BatchSM2Sign(tasks []*XTaskSM2P256Sign) ([]*XTaskSM2P256Sign, error) {
var eng Engine
eng = x.cpue
var tall = make([]XTask, len(tasks))
for i := 0; i < len(tasks); i++ {
tall[i] = tasks[i]
}
res, e := eng.ProcessBatch(tall)
var xs = make([]*XTaskSM2P256Sign, 0)
for _, t := range res {
xs = append(xs, t.(*XTaskSM2P256Sign))
}
return xs, e
}
func (x *Xecc) BatchSM2Verify(tasks []*XTaskSM2P256Verify) ([]*XTaskSM2P256Verify, error) {
var eng Engine
eng = x.cpue
var tall = make([]XTask, len(tasks))
for i := 0; i < len(tasks); i++ {
tall[i] = tasks[i]
}
res, e := eng.ProcessBatch(tall)
var xs = make([]*XTaskSM2P256Verify, 0)
for _, t := range res {
xs = append(xs, t.(*XTaskSM2P256Verify))
}
return xs, e
}
package cpu
import (
"github.com/CaduceusMetaverseProtocol/MetaCryptor/crypto"
"github.com/CaduceusMetaverseProtocol/MetaCryptor/xecc/engine"
. "github.com/CaduceusMetaverseProtocol/MetaCryptor/xecc/types"
"github.com/CaduceusMetaverseProtocol/MetaCryptor/common/log"
"sync"
)
var (
cpuEngine = &CPUEngine{}
)
type CPUEngine struct {
softTask chan *TaskWithReport
closed chan struct{}
ready bool
mux sync.Mutex
initOnce sync.Once
}
func GetInstance() *CPUEngine {
cpuEngine.mux.Lock()
defer cpuEngine.mux.Unlock()
cpuEngine.initOnce.Do(func() {
cpuEngine.softTask = make(chan *TaskWithReport, 100000)
cpuEngine.closed = make(chan struct{})
cpuEngine.ready = true
go cpuEngine.softtask()
})
return cpuEngine
}
func (ce CPUEngine) Ready() bool {
return ce.ready
}
func (ce CPUEngine) Support(task XTask) bool {
return true
}
func (ce CPUEngine) Name() string {
return "cpu-engine"
}
func (ce CPUEngine) Process(task XTask) (XTask, error) {
if e := ce.doTask(task); e != nil {
return task, e
}
return task, nil
}
func (ce CPUEngine) ProcessA(twp *TaskWithReport) error {
if ce.Ready() {
return SafeWriteXTaskWithReport(ce.softTask, twp)
}
return engine.ErrNotReady
}
func (ce CPUEngine) ProcessBatch(tasks []XTask) ([]XTask, error) {
success := make([]XTask, 0, len(tasks))
failed := make([]XTask, 0, len(tasks))
sch := make(chan XTask)
fch := make(chan XTask)
for _, t := range tasks {
go func(task XTask) {
e := ce.doTask(task)
if e == nil {
SafeWriteXTask(sch, task)
} else {
SafeWriteXTask(fch, task)
}
}(t)
}
for {
select {
case n, ok := <-sch:
if !ok {
break
}
success = append(success, n)
case f, ok := <-fch:
if !ok {
break
}
failed = append(failed, f)
}
if (len(success) + len(failed)) == len(tasks) {
break
}
}
return success, nil
}
func (ce CPUEngine) doTask(task XTask) error {
var err error
switch t := task.(type) {
case *XTaskSecp256k1RPubkey:
log.Info("recover pubkey with v", t.Rsig[64])
t.Pubkey, err = crypto.RecoverPubkey(t.Msg, t.Rsig)
if err != nil {
log.Error("recover pubkey failed", "err=", err)
} else {
t.Address = crypto.Keccak256(t.Pubkey[1:])[12:]
}
case *XTaskSecp256k1RSign:
t.Rsig, err = crypto.RecoverableSign(t.Msg, t.Privk)
case *XTaskSecp256k1Sign:
t.Sig, err = crypto.Secp256k1Sign(t.Msg, t.Privk)
case *XTaskSecp256k1Verify:
t.Verify, err = crypto.Secp256k1Verify(t.Msg, t.Pubkey, t.Sig)
case *XTaskEcdsa256Sign:
t.Sig, err = crypto.EcdsaP256Sign(t.Msg, t.Privk)
case *XTaskEcdsa256Verify:
t.Verify, err = crypto.EcdsaP256Verify(t.Msg, t.Pubkey, t.Sig)
case *XTaskSM2P256Sign:
t.Sig, err = crypto.SM2Sign(t.Msg, t.Privk)
case *XTaskSM2P256Verify:
t.Verify, err = crypto.SM2Verify(t.Msg, t.Pubkey, t.Sig)
default:
err = engine.ErrUnsupport
}
return err
}
func (ce CPUEngine) softtask() {
for {
select {
case s, ok := <-ce.softTask:
if !ok {
return
}
t := s.XTask
if e := ce.doTask(t); e == nil {
s.Report()
}
case <-ce.closed:
return
}
}
}
package cpu
import (
"github.com/CaduceusMetaverseProtocol/MetaCryptor/crypto"
)
func (ce *CPUEngine) Secp256k1RecoverPubkey(msg []byte, sig []byte) ([]byte, error) {
return crypto.RecoverPubkey(msg, sig)
}
func (ce *CPUEngine) Secp256k1RecoverableSign(msg []byte, key []byte) ([]byte, error) {
return crypto.RecoverableSign(msg, key)
}
func (ce *CPUEngine) Secp256k1Sign(msg []byte, key []byte) ([]byte, error) {
return crypto.Secp256k1Sign(msg, key)
}
func (ce *CPUEngine) Secp256k1Verify(msg []byte, sign []byte, pubkey []byte) (bool, error) {
return crypto.Secp256k1Verify(msg, pubkey, sign)
}
func (ce *CPUEngine) EcdsaSign(msg []byte, key []byte) ([]byte, error) {
return crypto.EcdsaP256Sign(msg, key)
}
func (ce *CPUEngine) EcdsaVerify(msg []byte, sign []byte, pubkey []byte) (bool, error) {
return crypto.EcdsaP256Verify(msg, pubkey, sign)
}
func (ce *CPUEngine) SM2Sign(msg []byte, key []byte) ([]byte, error) {
return crypto.SM2Sign(msg, key)
}
func (ce *CPUEngine) SM2Verify(msg []byte, sign []byte, pubkey []byte) (bool, error) {
return crypto.SM2Verify(msg, pubkey, sign)
}
package engine
import (
"errors"
)
var (
ErrUnsupport = errors.New("unsupported function")
ErrNotReady = errors.New("engine is not ready")
)
// +build opencl
package opencl
/*
#cgo CFLAGS: -I.
#cgo LDFLAGS: -L . -loclsp -lOpenCL
#include "oclsp.h"
#include <string.h>
*/
import "C"
import (
"errors"
"github.com/CaduceusMetaverseProtocol/MetaCryptor/xecc/engine"
. "github.com/CaduceusMetaverseProtocol/MetaCryptor/xecc/types"
_ "github.com/CaduceusMetaverseProtocol/MetaCryptor/xecc/engine/opencl/statik"
"github.com/rakyll/statik/fs"
"io/ioutil"
"sync"
"time"
"unsafe"
)
const (
clfsname = "/k.cl"
verifyOk = 1
cl_success = 1
msgLength = 32
rsignLength = 65
signLength = 64
pubkeyLength = 65
openclCPU = 1
openclGPU = 0
)
type OclMsg [msgLength]byte
type OclRecoverableSignature [rsignLength]byte
type OclSignature [signLength]byte
type OclPubkey [pubkeyLength]byte
var (
ocle = &OclEngine{}
ErrNotAlready = errors.New("OpenCL not already")
ErrLengthNotMatch = errors.New("param length not matched")
ErrCallFunctionFailed = errors.New("call function failed")
)
type OclEngine struct {
init sync.Once
mux sync.Mutex
already bool
closed chan struct{}
verifytask *basetask
recovertask *basetask
}
func GetInstance() *OclEngine {
ocle.mux.Lock()
defer ocle.mux.Unlock()
ocle.init.Do(func() {
code, e := getCLSourcode()
if e == nil {
go func() {
var codelen C.int = C.int(len(code))
var c_code *C.uchar = (*C.uchar)(unsafe.Pointer(&code[0]))
ret := C.secp256_ocl_init(c_code, codelen, openclGPU)
if ret == 0 {
ocle.already = true
ocle.closed = make(chan struct{})
ocle.recovertask = newBaseTask()
ocle.verifytask = newBaseTask()
go ocle.routine()
}
}()
}
})
return ocle
}
func (ocl *OclEngine) Ready() bool {
return ocl.already
}
func (ocl *OclEngine) Support(xTask XTask) bool {
id := xTask.TaskId()
if id == FeatureSecp256k1RecoveryPubkey || id == FeatureSecp256k1Verify {
return true
}
return false
}
func (ocl *OclEngine) Name() string {
return "opencl-engine"
}
func (ocl *OclEngine) doTask(task XTask) (XTask, error) {
var e error
switch t := (task).(type) {
case *XTaskSecp256k1RPubkey:
t.Pubkey, e = ocl.OclSecp256RecoverPubkeyS(t.Msg, t.Rsig)
return t, nil
case *XTaskSecp256k1Verify:
t.Verify, e = ocl.OclSecp256VerifyS(t.Msg, t.Sig, t.Pubkey)
return t, nil
default:
e = engine.ErrUnsupport
}
return nil, e
}
func (ocl *OclEngine) doBatchTask(tasks []XTask) error {
var e error
var num = len(tasks)
switch tasks[0].(type) {
case *XTaskSecp256k1Verify:
var batch = make([]*XTaskSecp256k1Verify, len(tasks))
for i := 0; i < len(tasks); i++ {
batch[i] = tasks[i].(*XTaskSecp256k1Verify)
}
var (
batchMsg = make([]OclMsg, num)
batchSig = make([]OclSignature, num)
batchPub = make([]OclPubkey, num)
batchRet = make([]C.int, num)
)
for i := 0; i < num; i++ {
copy(batchMsg[i][:], batch[i].Msg)
copy(batchSig[i][:], batch[i].Sig)
copy(batchPub[i][:], batch[i].Pubkey)
}
e = ocl.batchOclSecp256Verify(batchMsg, batchSig, batchPub, batchRet)
if e != nil {
return e
}
for i := 0; i < num; i++ {
batch[i].Verify = (batchRet[i] == 1)
}
return nil
case *XTaskSecp256k1RPubkey:
var batch = make([]*XTaskSecp256k1RPubkey, len(tasks))
for i := 0; i < len(tasks); i++ {
batch[i] = tasks[i].(*XTaskSecp256k1RPubkey)
}
var (
batchMsg = make([]OclMsg, num)
batchRsig = make([]OclRecoverableSignature, num)
batchPub = make([]OclPubkey, num)
)
for i := 0; i < num; i++ {
copy(batchMsg[i][:], batch[i].Msg)
copy(batchRsig[i][:], batch[i].Rsig)
}
e = ocl.batchOclSecp256RecoverPubkey(batchMsg, batchRsig, batchPub)
if e != nil {
return e
}
for i := 0; i < num; i++ {
batch[i].Pubkey = make([]byte, pubkeyLength)
copy(batch[i].Pubkey, batchPub[i][:])
}
return nil
default:
e = engine.ErrUnsupport
}
return e
}
func (ocl *OclEngine) Process(task XTask) (XTask, error) {
if !ocl.Ready() {
return task, ErrNotAlready
} else {
t, e := ocl.doTask(task)
return t, e
}
}
func (ocl *OclEngine) ProcessA(twp *TaskWithReport) error {
if !ocl.Ready() {
return ErrNotAlready
}
ocl.mux.Lock()
defer ocl.mux.Unlock()
switch twp.XTask.(type) {
case *XTaskSecp256k1RPubkey:
ocl.recovertask.add(twp)
case *XTaskSecp256k1Verify:
ocl.verifytask.add(twp)
default:
return engine.ErrUnsupport
}
return nil
}
func (ocl *OclEngine) ProcessBatch(tasks []XTask) ([]XTask, error) {
if !ocl.Ready() {
return tasks, ErrNotAlready
} else {
e := ocl.doBatchTask(tasks)
return tasks, e
}
}
func getCLSourcode() ([]byte, error) {
statikFS, err := fs.New()
if err != nil {
return nil, err
}
// Access individual files by their paths.
r, err := statikFS.Open(clfsname)
if err != nil {
return nil, err
}
defer r.Close()
return ioutil.ReadAll(r)
}
func cArrayToGoArray(ca unsafe.Pointer, goArray []byte, size int) {
p := uintptr(ca)
for i := 0; i < size; i++ {
j := *(*byte)(unsafe.Pointer(p))
goArray[i] = j
p += unsafe.Sizeof(j)
}
}
func (ocl *OclEngine) batchOclSecp256RecoverPubkey(msg []OclMsg, sig []OclRecoverableSignature, recpub []OclPubkey) error {
msgcount := len(msg)
if msgcount != len(sig) || msgcount != len(recpub) {
return ErrLengthNotMatch
}
//fmt.Println("in oclEngine")
//for i := 0; i < msgcount; i++ {
// fmt.Printf("task ---> %d, msg = %s, rsig = %s\n", i, hex.EncodeToString(msg[i][:]),
// hex.EncodeToString(sig[i][:]))
//}
ocl.mux.Lock()
defer ocl.mux.Unlock()
var (
cmsg = (*C.ocl_msg)(unsafe.Pointer(&msg[0]))
csig = (*C.ocl_recoverable_signature)(unsafe.Pointer(&sig[0]))
cpub = (*C.ocl_pubkey)(unsafe.Pointer(&recpub[0]))
)
cret := C.secp256k1_ecdsa_recover_ocl(C.int(msgcount), csig, cmsg, cpub)
if cret != cl_success {
return ErrCallFunctionFailed
}
//fmt.Println("in oclEngine after recover ")
//for i := 0; i < msgcount; i++ {
// fmt.Printf("task ---> %d, rpub = %s\n", i, hex.EncodeToString(recpub[i][:]))
//}
return nil
}
func (ocl *OclEngine) batchOclSecp256Verify(msg []OclMsg, sig []OclSignature, pubkey []OclPubkey, verifyall []C.int) error {
msgcount := len(msg)
if msgcount != len(sig) || msgcount != len(pubkey) {
return ErrLengthNotMatch
}
ocl.mux.Lock()
defer ocl.mux.Unlock()
var (
cmsg = (*C.ocl_msg)(unsafe.Pointer(&msg[0]))
csig = (*C.ocl_signature)(unsafe.Pointer(&sig[0]))
cpub = (*C.ocl_pubkey)(unsafe.Pointer(&pubkey[0]))
cverify = (*C.int)(unsafe.Pointer(&verifyall[0]))
)
cret := C.secp256k1_ecdsa_verify_ocl(C.int(msgcount), csig, cmsg, cpub, cverify)
if cret != cl_success {
return ErrCallFunctionFailed
}
return nil
}
func (ocl *OclEngine) OclSecp256RecoverPubkeyS(msg []byte, sig []byte) ([]byte, error) {
if !ocl.already {
return nil, ErrNotAlready
}
var (
batchMsg = make([]OclMsg, 1)
batchRsig = make([]OclRecoverableSignature, 1)
batchPub = make([]OclPubkey, 1)
)
copy(batchMsg[0][:], msg)
copy(batchRsig[0][:], sig)
err := ocl.batchOclSecp256RecoverPubkey(batchMsg, batchRsig, batchPub)
if err != nil {
return nil, err
}
return batchPub[0][:], nil
}
func (ocl *OclEngine) OclSecp256VerifyS(msg []byte, sig []byte, pubkey []byte) (bool, error) {
if !ocl.already {
return false, ErrNotAlready
}
var (
batchMsg = make([]OclMsg, 1)
batchSig = make([]OclSignature, 1)
batchPub = make([]OclPubkey, 1)
batchRet = make([]C.int, 1)
)
copy(batchMsg[0][:], msg)
copy(batchSig[0][:], sig)
copy(batchPub[0][:], pubkey)
err := ocl.batchOclSecp256Verify(batchMsg, batchSig, batchPub, batchRet)
if err != nil {
return false, err
}
if batchRet[0] == verifyOk {
return true, nil
}
return false, nil
}
func (ocl *OclEngine) routine() {
for {
timer := time.NewTicker(time.Millisecond * 100)
select {
case <-timer.C:
if ocl.verifytask.ready() {
ocl.mux.Lock()
t := ocl.verifytask
ocl.verifytask = newBaseTask()
ocl.mux.Unlock()
{
var batch = make([]*XTaskSecp256k1Verify, len(t.tasks))
var num = len(t.tasks)
for i := 0; i < num; i++ {
batch[i] = t.tasks[i].XTask.(*XTaskSecp256k1Verify)
}
var (
batchMsg = make([]OclMsg, num)
batchSig = make([]OclSignature, num)
batchPub = make([]OclPubkey, num)
batchRet = make([]C.int, num)
)
for i := 0; i < num; i++ {
copy(batchMsg[i][:], batch[i].Msg)
copy(batchSig[i][:], batch[i].Sig)
copy(batchPub[i][:], batch[i].Pubkey)
}
e := ocl.batchOclSecp256Verify(batchMsg, batchSig, batchPub, batchRet)
if e != nil {
//Todo: deal with error.
}
for i := 0; i < num; i++ {
batch[i].Verify = (batchRet[i] == 1)
t.tasks[i].Report()
}
}
}
if ocl.recovertask.ready() {
ocl.mux.Lock()
t := ocl.recovertask
ocl.recovertask = newBaseTask()
ocl.mux.Unlock()
{
var num = len(t.tasks)
var batch = make([]*XTaskSecp256k1RPubkey, num)
for i := 0; i < num; i++ {
batch[i] = t.tasks[i].XTask.(*XTaskSecp256k1RPubkey)
}
var (
batchMsg = make([]OclMsg, num)
batchRsig = make([]OclRecoverableSignature, num)
batchPub = make([]OclPubkey, num)
)
for i := 0; i < num; i++ {
copy(batchMsg[i][:], batch[i].Msg)
copy(batchRsig[i][:], batch[i].Rsig)
}
e := ocl.batchOclSecp256RecoverPubkey(batchMsg, batchRsig, batchPub)
if e != nil {
//Todo: deal with error.
}
for i := 0; i < num; i++ {
batch[i].Pubkey = make([]byte, pubkeyLength)
copy(batch[i].Pubkey, batchPub[i][:])
t.tasks[i].Report()
}
}
}
case <-ocl.closed:
return
}
}
}
package opencl
import (
"bytes"
"encoding/hex"
"fmt"
"github.com/CaduceusMetaverseProtocol/MetaCryptor/xecc/types"
"io/ioutil"
"testing"
"time"
)
type recoverCase struct {
hash string
rsig string
pubk string
}
var recoverArray = []recoverCase{
{
hash: "31920d1ef030c8296c85c29e4658b1a29e2fea41af7ddad24dc6bc59c6e23c8d",
rsig: "ccc8e751834ddacc76773c9638f506e049840166eb025152ec5fb7d34b50feb06d95e1f220c8031ed73e8608f09f5de14cddb8122c3c0ec4ce26c42a2274e80b01",
pubk: "0481903830e01769fe48c372c1c02ce7fefbf042c3fde1f1cb74d3ada4465e26eeacb1f020b347614ab7e2dedb71e2efaa89e2a8661960839f72f6dde95d5eff3f",
},
{
hash: "e5312bc72030bb1c356e29f6047bd663e663d096ada0beb858081a4d3b55bf12",
rsig: "290a4d4e585f28db796dae3ced74130fabffead3b5c2923304e1761fb9ca936a09728351c56a4294df0c1fc387931d5cff7f59eadb1084bace16af61a341ef8601",
pubk: "0481903830e01769fe48c372c1c02ce7fefbf042c3fde1f1cb74d3ada4465e26eeacb1f020b347614ab7e2dedb71e2efaa89e2a8661960839f72f6dde95d5eff3f",
},
{
hash: "e04ab1e1892445ed18c7caa515e593e69eddea7250a9076bffbbc6aac87593ae",
rsig: "f8e53a45b4607cc4044439b4caac56179df941543f8bab6c6be6de681f7e1ee467591d058ab8660cf103b89ea749e75e2cd3c2b34fac4b3620b1b37b0542a72500",
pubk: "0481903830e01769fe48c372c1c02ce7fefbf042c3fde1f1cb74d3ada4465e26eeacb1f020b347614ab7e2dedb71e2efaa89e2a8661960839f72f6dde95d5eff3f",
},
{
hash: "72804c483b95fb866712ca175bd431214f46916fad5437b577772b0dd135e9f3",
rsig: "8fe82a947d922451f2fe2011bb63311248ff79fb9a88d2d28d3779ae80b7090664d9990c1f3077ca4f691af9594974f0be979a3801f65705757b86344fbe2b6601",
pubk: "0481903830e01769fe48c372c1c02ce7fefbf042c3fde1f1cb74d3ada4465e26eeacb1f020b347614ab7e2dedb71e2efaa89e2a8661960839f72f6dde95d5eff3f",
},
{
hash: "0824caafe5252483719d49ce28e0968d5f927d24ce96b31c5de48d0133ab3373",
rsig: "507f3caa9b0a3ccbf0e063fa21f0e765dab423a667268d9ce7101d2b8034e6fc44cb391b950fe8306e07b46e8df8bc9e10dd12c44100382861420d7f315db80f00",
pubk: "0481903830e01769fe48c372c1c02ce7fefbf042c3fde1f1cb74d3ada4465e26eeacb1f020b347614ab7e2dedb71e2efaa89e2a8661960839f72f6dde95d5eff3f",
},
}
func init() {
e := GetInstance()
for !e.Ready() {
fmt.Println("wait opencl init")
time.Sleep(time.Second)
}
}
func TestGetCLCode(t *testing.T) {
origin, err := ioutil.ReadFile("code/k.cl")
if err != nil {
t.Error("read origin data failed")
}
fsk, err := getCLSourcode()
if err != nil {
t.Error("get fsk data failed")
}
if bytes.Compare(origin, fsk) != 0 {
ioutil.WriteFile("fsk.cl", fsk, 0755)
t.Error("content compare failed")
}
}
func TestRecover(t *testing.T) {
ocl := GetInstance()
strhash := "e5312bc72030bb1c356e29f6047bd663e663d096ada0beb858081a4d3b55bf12"
strsig := "290a4d4e585f28db796dae3ced74130fabffead3b5c2923304e1761fb9ca936a09728351c56a4294df0c1fc387931d5cff7f59eadb1084bace16af61a341ef8601"
strpub := "0481903830e01769fe48c372c1c02ce7fefbf042c3fde1f1cb74d3ada4465e26eeacb1f020b347614ab7e2dedb71e2efaa89e2a8661960839f72f6dde95d5eff3f"
//error pub
//strpub := "0481903830e01769fe48c372c1c02ce7fefbf042c3fde1f1cb74d3ada4465e26eeacb1f020b347614ab7e2dedb71e2efaa89e2a8661960839f72f6dde95d5eff3s"
var msg, sig []byte
msg, _ = hex.DecodeString(strhash)
sig, _ = hex.DecodeString(strsig)
expectpub, _ := hex.DecodeString(strpub)
ts := time.Now().Nanosecond()
pub, err := ocl.OclSecp256RecoverPubkeyS(msg, sig)
if err != nil {
t.Error("Recover failed")
}
te := time.Now().Nanosecond()
if bytes.Compare(pub, expectpub) != 0 {
t.Error("compare failed")
t.Log("pub", hex.EncodeToString(pub))
}
fmt.Printf("recover cost %dus\n", (te-ts)/1000)
}
func TestVerify(t *testing.T) {
strhash := "02030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021"
strsig := "e8a97e31f8f5dde21b7394b190ed149ba0e28ddfdd44a170d21eb60f37bd132c04909be5273908befbe6166a9cb3f38fbb19c8cfff1d1561f4d61dfa0c499a81"
strpub := "041d17bd8d96b4bdf49dd1436e5af4f0bd3bff939df8cf8fdc1f621e3c89de2a47111eb88b4bb89f180702a8bc744d5a37615965713d1fdfff000c2a62b4aea409"
// error pub
//strpub := "041d17bd8d96b4bdf49dd1436e5af4f0bd3bff939df8cf8fdc1f621e3c89de2a47111eb88b4bb89f180702a8bc744d5a37615965713d1fdfff000c2a62b4aea404"
var msg, sig []byte
msg, _ = hex.DecodeString(strhash)
sig, _ = hex.DecodeString(strsig)
pub, _ := hex.DecodeString(strpub)
ts := time.Now().Nanosecond()
verify, err := GetInstance().OclSecp256VerifyS(msg, sig, pub)
if err != nil || !verify {
t.Error("Verify failed")
} else {
t.Log("Verify successful")
}
te := time.Now().Nanosecond()
fmt.Printf("verify cost %dus\n", (te-ts)/1000)
}
func TestProcess(t *testing.T) {
var tasks = make([]types.XTask, 0)
var okpubs = make([][]byte, 0)
for _, info := range recoverArray {
task := &types.XTaskSecp256k1RPubkey{}
task.Msg, _ = hex.DecodeString(info.hash)
task.Rsig, _ = hex.DecodeString(info.rsig)
pub, _ := hex.DecodeString(info.pubk)
tasks = append(tasks, task)
okpubs = append(okpubs, pub)
}
for i, tm := range tasks {
fmt.Println("test index ", i)
ts, e := GetInstance().Process(tm)
if e != nil {
t.Error("process failed", e)
}
if bytes.Compare(okpubs[i], tm.(*types.XTaskSecp256k1RPubkey).Pubkey) != 0 {
fmt.Println("compare pubkey failed", "got", hex.EncodeToString(tm.(*types.XTaskSecp256k1RPubkey).Pubkey), "expect ", hex.EncodeToString(okpubs[i]))
} else {
fmt.Println("tm got correct pubkey")
}
if bytes.Compare(okpubs[i], ts.(*types.XTaskSecp256k1RPubkey).Pubkey) != 0 {
fmt.Println("compare pubkey failed", "ret got", hex.EncodeToString(ts.(*types.XTaskSecp256k1RPubkey).Pubkey), "expect ", hex.EncodeToString(okpubs[i]))
} else {
fmt.Println("return value got correct pubkey")
}
}
}
func TestProcessBatch(t *testing.T) {
var tasks = make([]types.XTask, 0)
var okpubs = make([][]byte, 0)
for _, info := range recoverArray {
task := &types.XTaskSecp256k1RPubkey{}
task.Msg, _ = hex.DecodeString(info.hash)
task.Rsig, _ = hex.DecodeString(info.rsig)
pub, _ := hex.DecodeString(info.pubk)
tasks = append(tasks, task)
okpubs = append(okpubs, pub)
}
rets, e := GetInstance().ProcessBatch(tasks)
if e != nil {
t.Error("process failed", e)
}
for i, m := range rets {
if bytes.Compare(okpubs[i], m.(*types.XTaskSecp256k1RPubkey).Pubkey) != 0 {
t.Error("compare pubkey failed", "got", hex.EncodeToString(m.(*types.XTaskSecp256k1RPubkey).Pubkey), "expect ", hex.EncodeToString(okpubs[i]))
} else {
fmt.Println("return value ok, task", i)
}
}
for i, m := range tasks {
if bytes.Compare(okpubs[i], m.(*types.XTaskSecp256k1RPubkey).Pubkey) != 0 {
t.Error("compare pubkey failed", "got", hex.EncodeToString(m.(*types.XTaskSecp256k1RPubkey).Pubkey), "expect ", hex.EncodeToString(okpubs[i]))
} else {
fmt.Println("param value ok, task", i)
}
}
}
#ifndef OCLSP_H
#define OCLSP_H
typedef struct {
unsigned char data[65];
} ocl_recoverable_signature;
typedef struct {
unsigned char data[64];
} ocl_signature;
typedef struct {
unsigned char data[32];
} ocl_msg;
typedef struct {
unsigned char data[65];
} ocl_pubkey;
int secp256_ocl_init(unsigned char *code, int codelen, int mode);
int secp256_ocl_destory();
int secp256k1_ecdsa_recover_ocl(int count, ocl_recoverable_signature *rsigall,
ocl_msg *msgall, ocl_pubkey *pubkeyall);
int secp256k1_ecdsa_verify_ocl(int count, ocl_signature *sigall,
ocl_msg *msg32all, ocl_pubkey *pubkeyall, int *resall);
#endif /*OCLSP_H*/
// +ild opencl
// Code generated by statik. DO NOT EDIT.
package statik
import (
"github.com/rakyll/statik/fs"
)
func init() {
data := "PK\x03\x04\x14\x00\x08\x00\x08\x00\x06F\x19Q\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00 \x00k.clUT\x05\x00\x01L\xd0D_\xec\xbd{w\xdb6\xf20\xfc\xb7rN\xbe\xc3t{~\xae$\xd36o\xa2\xe4\xca\xf2s\xd2\xd4\xd9\xf6\xfd\xa5\xed6M\xdf\xf56\xeb\xe8P\x12m3\x95(\x85\xa4b\xd9\x9b\xecg\x7f\x0en$\x00\x02 \xe5\xc4i\xf7Ye\xb7\x96D\x0c\x063\x83\x99\xc1`p\xe1Q\xf7\xf1#\xe8\xc2O\xab(y\xfa\x1c\xbe_\xac\xe6\xd1\"Jr\xf8%\x9a\xae\xdc^\xf0\xbb\x03\xef\xa24\xbe\xbc\x850\x99A\x1aM\x97\xef\xa2\xf4\x10U9z\xfc(\xbf]E\xb3\xe8\x12\xd6\xf3er\x05\xeb8\xc9\x03\x7f\x9c\x0f\xb9\x828\xc9\xf1\x1f\xcf\xc5\xcf\x1f?\xfa2\xbeD\x05\xdf\x9e\xbd<{\xf1\xc3\xf7?~\xff\xcb\xcb\xef\x9f>~\xf4\xe5,\xba\x8c\x93\x08\x9e~w\xf6\xf4\x7f\xdb\xd3e2\xeb\xc0l \xff\x82\x7f>~\x04\x00\x10_B\xfb\xec\xfcogO_\xb6\xbf \xc5\x16\xd8\x9dN \x80\xfe\xbd<\xfb\xe5\xe5\xf8\xd9\x93\xef\x9f\xff\xfa\xe2\xac\xfd\x97<\xcar@\xa0q\x1e/\x13\xb8\x0c\xe3y4\xfbKg\xc8j|@_>\xc0\xcdu<\x8f\xdav\xe7\xf1\xa3/\xa3y\x16}>R\xbe\x86\xbf\xc0\x97\xb8\xbe\x89\xa4d\x16_\"\xb1\x1du\xe1y\xfc{\x04a\x96Ei\xde\xeeX0Y\xe7ps\x1d%\xf0\xff\x9f\xbd\xf8\xfe\xd9? \xce\x80P>\xb3pWe\xf1,:\x88./\xa3i\x0eYx\x19\x1d\xe2\x1e\xa3\xe2'uJf\xc9\xef1\xe6\x99p^)\xfb\xe5\xec\xe5\xaf\x7fkg\xf9\"\xa7\xf2@_\x87`\x90 \x8f\x94\x17d\xfb\xdd2\x9eu\xda\x94w\x01\x81\xb6I^\x16\x0c\xea\x97\xb3\xa7\x7fs{\xc1\xff:\xe3\x17g\xbf\xbc|\xf1\xfd\xd3\x97e\xd9\xdf\xbf\xff\xf1\xdb\x9f\xfe>~\x02=\xa8<\xfc+8A\xf9\xf0\xec\xe9\x0f\xbf>\x7f9~\xf9\xe4\x9b\xe7g\xe3_\xbe\xff\xed\xac}\xd3\x81\xb6\x03''\xd0n\xdft\x0e\xdcN\x87v\xc0\xaf\xc9*\x9c\xfe\x9eA\x88\xfa2\xcb\xc3$\x878\xc9\x97\x10\x02\xb2\x89y\xb8Z\xc5\xc9\x15,\xd6\xf3<>\x98\xc7\x8bI4\x83gg\x10\x11{\xa2\xe2\xaf\x90\xfe\xecl\xfc\xf4\xa7\x1f\x7fy9\xfe\xfe\xc7\x1f\xcf^\xb4g}\x0bf\x81\x05\xb3\x9e\x053\xdf\x82\x99g\xc1\xcc\xb5`\xe6X0\xb39-k\xa3_{`o\xbcg\xf8\xdf\xaf\xcf\xad\xa2\xa8\xddf&\xd7AP\xa7\xa7\xe0\x06\x1dx/\x14\xb4g\x0e\xa9Okw\x10\xc3AG\x8d\xc4!H\xec*\x12\xb7$\x82\xe2p\\\x0d\x12\x17#q\xfc*\x12\x8fQ\xc2P\x0c4(<\x8cbP\xc5\xe0S2(\x02\xd7\xd7 \xf0 #\x8d$Ga\x15\xad\xf5\xf8\xfa\xb4I]\x8b=\x82\xc5\xadb J\xf93\xbem\x0d\x92\x80\x88N\xd1\x89\xfd\x82\x14\x86C\xd7\x87}\x82\xc3\xee`'\xa3\xb6#\xa6\x8c\xf5j\xa8U`D\x92\x05\x88;\xf4\xb7\x87\xff\xfa\xf8\xaf\x87\xff\xba\xf8\xaf\x83\xff\xda\x9d\x8e\x05\x8e\x05\xce\x87\xc2\xc5-&\x19,/!\xbf\x8e +\x06\xa0e:\x8bR\x9d\x01\xfd8\xb6\x81\xe3\xd3\xde|k{\x81\xef\xf8\xce\xaf\xcf;jxG\x84\xff\xe6\xd9\xb7n\xefl\xf0T\x0b\xef\x8a\xf0O\x9e\xf9\x83'\xb6\xf7\x8d\x16\xde\x93\xf0?yr\xf6\xed\xd3\xb3@\x0b\xef\x8b\xf0D+\x9f\x9di\xe1{J\xf8gZ\xf8`K\xf8\xbe\x01^\xec&\xf7\xb5\xdb\x0b`\x11'\xebl\xbb.{\x8a:\xed\xdfb'\xee\x83\xa3!\xe8)\xea2\x01Z\x0f\xe9J\x90\xae\x16\xd2\x93 =-\xa4\x0fm\xa7\xc2\xfbu8\xdfRO\xbf\x9355\x188\xdf\xb8\xf6\x13[\xdb\x13\xdf\xc9\xba\xfa\xed\xb3\xb3c\xf7\x99\xaf\xd7\xa5\xefdm\xed\xf5\x9f\xf8=\xdb\xf9\xd6PC\xd2\xd7\xde\xb7\xbd~p\xd6\xf7\x0c5\xd4\x1a\xab\xd7\xa8\xef\xb6\xd6\xd9\xef\xb6\xd6\xda\xefd\xbd\xed\x8bz\xcb\xea,\xd6\xf3p6k\x87\xd6\x84\x8e\xa6-V\x07\xf2\xb9\x05\xf95\x0e\xc7Z\xa4\x08\x97\xa1\x98\x16r\x18A\x9b\xfd\xea\x84\xd0\x85 \x01l\xe5\xd70\x82\x1c9W\xcf\x1d\xb6Z\x00G]\x08sX,\xb3\x1cJk\x86\xee\x11\x05\x9f#pR\x17\x07|\xad\xa9\x0d\xfb#\xc8\xe7\xc3V\x8bVG\xf1\xc4\xe5|y\x83\x82\xba\xeb0\x99\xcd\xa3\x19,\x13\xacmI\xb4\xc9a\x8e\x18\xa1\x08\xf3kT\xbb=\xb5\xe1\x04\xf2y\x07\xfe\x0f8\xf05\xd8C5\x1d\xcfX\xb5\xa9\x83\x1b\xbd\xbe_\xa3S\x974\xea\xa0F\xaf\xa5F\x93\xe8]\x94\x16\xe82\x98\xdc\xa2\x80)O\xc3i\x0em<\x99\x88\xa3\x19\xc4\x12\xea\x0e\xc5M\xc7\x82.<\x99\xcd \xecN _\x12\xc0\xf5b\x12\xa5,\xc6EH\xdbS\xdb\x9a:\x9dC\x98:\xb0Xg\xb9\xd4\xb0h\x88\xa4\xdb\xc7\x97a\x96\xef\xfa\xbe\xd2\xf7\x9f\xb0\xcb\xdcn\x83N\xb3\xa6.\xea7\xb7i\xbf\xb9\x86>C\xff\xb9\x16\xe4s\xf7#{\xaf\xd5\xda\xb6\xf7\xf2k\x17=\xba\x86}&M\x0d\x8av\x9c\xc04\xcc\"\x04{\x13fPz\xa7\x8edR\x08\xa5hS\x18g\xb3\x0eR\xf6NK\x98\x87\xe1\x06NG\xb8\x85\xf7\xef\xa1=u\xe1\x8b\x11\x9a\xc0\x12\xbe\xf29\xe6h\x8e8\x9a7\xe4(\x82\xf9\xf2\x06Mq\x03\x0f&qN\x02\xb89\xdcDi\xa4b\x14\x11\x809\x9d\xbb\x92\xda\xaa\xdb*\xd5\x96\xda\n\xe9+\x0c\xbc\x9d\xb1\xb8\xbc\xb5\xb8R\xbbY\x84&\xa4[a\x9c\xca\x08\xf7H\xff\x8d\x90@\x87\x9f\xb6\xdb\xa66\xee5\xd4\n\xea6\xd4\x0c\xee7U'2\xfb\xbe\xa7\xa0D\xe7.\xcb\xe9#X\x12]\xfb\xa7\xf3\x11\xd9z\x81\x87\xf4\xc2A$Y|\x95`\x87\x95\xe3*CN\x7f\xdaagx\x1f\xa9 X`\xbd\xdd\x0e;\x9c\xb7-eN\x1a\xbb\x07v^\xe6\xa8\x1e'\xf4\x1a\x99\xdfG\xb4\xda1\xd3*\xe4=\x89\xe0.J\x97*A\xd3A\x94I[\x14+l=\x88\x11\xc9\xa9\xe4\xda|djdA\x0e\xb3\x18\xa0\xd6\x84Z\xa3&#\xe6\xaa\x98 \x0b\x92=\xdb\x90V9\x87\xe7\xb9\x85\xc3+u\x96$\x85\x12\x92\x85\x9bG\x979d\xd7\xf1e\xcew\x08\xad'\n7\"\xf8\xdb \x13,\xfa6\x82\xa9]h\xef\x08\xa6N\xa1m#\x98\xd2\x01\x0f\x91K\xd5\xf0A\x89\x9d\xba\xa8;\xd3\xe8\xed:N\x91\xcc\x97j%\xa1|\x10-i\xcc\x8c\xdd\xa8\x1fX^9\xcb\xd3\xf54\x87\x7f\x91<G\x11\x10\xcc^\x0d.\x86\x8f\x1f}(\xe7d\xe3l\x1a\xce\xc3\xf4|\xd8\xa0v\xf2\xca\xb1Qu\x9c\xe5MrX\x84WI\x9c\xafg\x11\xf7,Y\xa6\x8bp\x1e\xdfE3\xa9\x9d\xcb\xc8\xd4\x86\x00\x07\x9b\xa1\xea\xe9-\xd7L\x9c\\\xc6I\x9c\xdf\x0e\x91 \xdc\\G\xf9u\x94B~\x8d\xc5\xbfJ\xa3,Jr2\xe3^-\x11xX\xd6\xc0]\xc1\x13v\xb5\x15a8p\x9c\xe6\xebp\x0e\xe7_\xc3\xe6\xe8\xee\xb5\x8b1\xaa\xc8\xe5`\xff\xf15\xdc\x1e\xdd\xbd\xf64\xb0w\x0f\xc5\xda\x9b\x86\x1d[Q\x8b\xcbh\x9c\xe5\xcb4l.\x9d\x02^\xd9}e\xe9\xedP&\xb2IK\xc5\x905\xbd\x0eS\x98\x85y\xf8*\xf0e\xa2\xa3\xe9,\x0b\xc7\x080\xcc\xd7\xe9\xc7\xe3[\xad'\xbfG\xb7\x04\xcdx\\$\xb5\xc5\xbe\x93\x9b\xc7`\xe3\xd5\x18g}\xc68\xe5q\x0e#U\x12\x91Pb[\xf4\xff\x8e\x05\xf6\xc6\xef\xf5\x1c\xd7s\x8e\x7f}\x8e~\xf5\xeco\xfa\xbdgO}\xf2\xcb\xb7\xddo\x9f8}\x97\xfcr\x9f==\xfe\xe6\xc9\xd9\xd9\xaf\xcf\x1f?\xea\xdc\x87DL\xda8\xcc0\x88\x89@.\xb7`5\xfbu\xf6\xebs\x8bU.\xd3{\x08\xa0L\x0e\xa2_ej\x11\xfd*\x13\x93\x8c\xa3X`\x85\xb8\xaa\xf1\xf4:\x9a\xfe>f#\xdey\xbb\xe2\xcb\xa0\x8b\xc6\xde\xd2\xa2n\xa3\x0c;\xd0\xc7\x8fZ\xc4E\xb1_\xc9\x12\xde\xa3Q\xee\xe0t\xf6\xaa\x7f\x01'b\x96\xaf\x83-\xf0\xc7%$Q4\x83\xcbe\n!\x9c\x02n\x9d8t\xa1~ \xd7\x0f\xb6\xab\xdf\x93\xeb\xf7\xb6\xab\xef\xcb\xf5}$\xc2\x16\xe2\x9d\x879\x95``\x0f\xfe\x9d,eax22\xbc\x02\xf1\xef\xdb(\xab\xe0\xf4d\x9c\x9e\x06\xa7+\xe3t\xb58]\x19\xa7\xab\xc1\xe9\xc88\x1d-NG\xc6\xe9p8\x05H\xfb\x02\xc5>B\xee\x95\x03M\xa3|\x9d&@\x9a\xf8\xa0U\xd24\x9a\xad\xa7\x91R9S\x0b*\x018\xd2\xe4\x0e\xef\x97\xc9\xcc|(\x8f\xf8E\xdcx2\x02\x07w\xb08{O)\x03\xfbe\x84\xd9\x95\x13\xcb\x98\x0b\n\x87\xa6\xf7{\x82\x15\x0f\xf1\x84\x7f\x84f\xfc\x18\xfb~\x05\xbdcD\xef\x14\xe8\x9d\xfb\xa1w\x8d\xe8\xdd\x02\xbd{?\xf4\x9e\x11\xbdW\xa0\xf7\xee\x87\xde7\xa2\xf7\x0b\xf4\xfe\xfd\xd0\xf7.\n\x0c\xbd\xfba\x08J\x0c\xc1\xfd0\xf4K\x0c}%\x86\xd2J\x98 \x98\xa9dy\x98\xc7Sx\xb7\x8cgU\x93\xc9\xa2|<\xf1\\\x9d\xcd\x8c\xc7W\xf3\xe5$\x9c\x93\xc5ei\x00\xefN<\xd7\xc2\xd6\xd4\xad\x98S1\xc9\x15\xf4\xbe\xcc\x84O<\xf7\x95\xe7\\\xa0i\x8f\xf8\xcc\xbe\x80\x93\x13\x18T\n\xdc\xe3\x0b\xb2\x92X-\x19\\\x90\xe5U\xd1\x08$\xa0~\xb5-7\xd0\xb5\xd5\xd3\xb6\xe5\xcbm\xb9\x8a\xb6<E[\xae\xae-G\xdb\x96-\xb7\xe5U\xdbr\x8e\xabm9\x03M[N_\xd7\x96\x13\xc8m\xf9\x8a\xb6z\x8a\xb6|][\x9e\xb6-Wn\xab\xa7hK\xa1\x1b\x8eN7\xb4\xaaQ\xd1\x8c\xa0\xda\x92B1tz\xa1U\x8b\x8aV\xf4\x15\xda\xaeP\n\x9d\xect\xed\xf0\x1aAS?\xdaA0\xb5\xea\xa3\xb8\xb4\x83\x87\xb3\xf8\x12\xda\x82\x05\xb7Z\x85E\xc3\xa8\xb0\xe3\x0f\xdc\xd8\xbb\x88\x16\xd3\xc5\xea\xbc-y\x84\xcc\xb1d'\x91Q\x1f1\x8f\x92\xce\xe3G\xff\xa2\xf1`\xcc\xc2\xc1\xcbe\xda\x8eG\xf6\x10b8A0C\x88\xf7\xf7;\x8f\x1f\xb50\x19\xf1e;s^\xc5\x17h\xca\x9d\xb9\xaf\xe2\x0bJ^k\xbaL\xf28Y\xa3Yp\x0b\x11\xc6\x81\x9eRH\x0cG}\"\x1e K\x90\x13\x05\xc8\x81Cyd\x0fl\xe6@\xb1\xe7D\x0c\xafn\xcf\xf16!\xe8\xce\xa2,\xafxGR\x94\xa5S\x0b\xb2\xf8.\x1as<\x03\x15\xc6\x0cF\x80\xea\xe2\xc9\x9aT\x9d\x8a\x0b\xf5i:\xc5\x00x\x0f\x12\xb4\xe7Qrp\xd0!~\xb5;\xdb\xdf\x87\x11t\xb3\xfd}\x05y\xe3|Iq\xb6\x0b\xe4<\xc1\x0d\xe8,\x89\xaa\x12\xfc \xe8\\\xa5\xf1\xbb0\x8f\xc6\x84\xde\xf6V\xc4\xb5\x14$\xb5t4\xb5\x14D\xb5\x14T\xa9G\xc7\xcbhL6\x18\x9e\xb7I\x03\xe2\xdc\x8e\x9b\xeb\xd0\x81\x91Z)\xa1.<8M\xf8\x94\x0d}Tdih2\xd1\x85.z^dt,@\x06\xed\xd0\x9a)\xec\x8d\xa0\x8d\x07\xce\x93\x11\xbf1\x08\xba\xb0\xe8H@N\x13 \xb7 \x90\xd7\x04\xc8o\x02\xd4k\x02\x144\x01\xea7\x01\x1a4\x01:\xa6@\xb6\xa7\x05\xe2{\x04\xcdIlC\xf1 \n\xd9X9\xf2\xa2B7\x17:\xa2\xaf\xed\xb0\xca\x0cA\n{{\x94\xd0\x91@hG\xc0\x06|&i\x11c\x93@\x12\xd8\x03,-\xf4\x11\x90\x8f\x1e\xf9\xf0\xc9\x87G>\xdc\x8b\xa1\x88\x0b5\x8d\xd1\x08\x12\xac4 \x05#m:%\xb17\xbe\xfd\xebs\xd8\xc7Ol\xf2\xc4\xfb\xd6Au\xc9\x0e\xbf\x8e\xd4+\x1d\xa9\xe5\x0f\xe5O\xfa\x95~\x08S\xb0\x14Q\x86\x85\xa5\x9f\xfd\xc5\xd9\xf8.J\x97U\x8bUd(\xa8\x8b/\xe6\x9e\xef\x81\xcdW\xe97\xb7\xf8\xe6\x15\xdf\xfc\xe2[\xaf\xf8\x16\x14\xdf\xfa\x17\x1d,>\xc1\xddU\xe3\xed\xb7\xe9\xb8\xe7\xb8\xe7\xed\xd2c\xcc\x99\xeb3R|\xd4\x85\xe3\x00&q\x0e\xe1t\xba^\xac\xe7a\xbe\xa4\xdbz\xca\xb5g\x9c\xc1\xb6- \xc9k\xbcnB(z\xfc\xa8u\xd4\x85\xf9+\xfb\xf0\xd0\xc1\xd1V\x88\xbe\xf6/^\xbb\x14\x85\xb0\x13\x81\x08\xc5\x02\xfa\x05\xc7\x08B\x02}\xce\x9e\x16\x0b\xe1B\x15G\xa8\xd2\x9e\xb3\x07jh\x97/dy\x03\x1d&\xd7\x84\xc9S\x14:R3%*\x15t\x81\xca7\xa1\xf2\xaa\x14\xbb\xdafT\x98\x8afz\xa6fT5]\x89\x86\xb2\x1d\x15\xaa\xa2\x9d\xc0\xd4\x8e\xaa\xa6\xab$\x82e\x9ft4\xa8\x9a)h\xe8\x9bhP\xd5tM\x04z\x12\x81%\x11\xc6vT\x85\xae\x89\x08OID\x9b6\xad\xa3a`jFE\x83g\xa2\xc1\x97h(\xdb96\xa1R\xb5\xe3+\xdbiS\xec\xbaf\x1c\x95\xb9\xfb\xa6vzR;\x1c.\x953\xe8)q\xb5)\x06-*\x957\x08$T\x1c\xb8`\xb7\x9c\xaf\xeb\xab\xab0_\xe7\xd0\xee\x15\x97\x01\x1d\xba\x0c\xf8\xf8Qk\xfe\x8a8\xd5\xa9\xdd(\xe7Bfhd\x18P\xa7]\xe4\xa0r^MS\xa2(\xb7t\xfc r\xfcH\xed,H\x1c\xfc\xf5\x18}u\xf1W\x07\x99`\xe2\x91\xef\xc8\x12\x12\x9f|G\x1a\x99\xf4\xc8w\xa45I@\xbe\xa3\x9eM\xfa\xe4;I~\x95\xb1\x86m\xc1\xc2\xb1`\xe1Z\xb0\xf0,X\xf8\x16,z\x16,\x02\x0b\x16}\x0b\x16\x03\x0b\x16\xc7\x08\x06\x03\"H\xc7\x150\xacl\x0bV\x8e\x05+\xd7\x82\x95g\xc1\xca\xb7`\xd5\xb3`\x15X\xb0\xea[\xb0\x1a\x14\xe3U\x93\x01\x0f\x0dvh\xa0+*\xbd\xc0\xd2\x85\x9eCW\x96\xf1Z\xb27\xe8\xd1\xaaG]X\xe0a\x10'n\xe6d\x18\x84}H\xe87){HkM\x89|\xed\x8b!\xb0\x85\xe1bl\x15\xf4)\xb1-9\xf5[U\xa9\x05y\xc6o\\\x90\xc6\xc8v\xe2\xa8\xf1\xb0\xe2J3\x8e\xa0\xec\x0b\x87kA\x1e6\xdb\x89kF^i\xdb1\xb7\xed\x8am\xbbb\xdb\xe2h\x99x\xe6\xb6+\xa49f\xd2\\3i\x9eH\x9a'\x92&\x0en\x89o&\xadB\xb9c\xa6\xdc5S.\xd0\x92\xd8\"\xa1\xbeH\xa88\xf8$=3\xa1\x15>\x1c3\x1f\xae\x99\x0f\x91PI\xd1z\"\xa1\xe2\xb0\x92\x04fB+|8f>\\3\x1f\"\xa1\x92V\x06\"\xa1\xe2@\x93\xf4\xcd\x84V\xf8p\xcc|\xb8f>DB%\x1d\xed\x9b s\xcc\x84\xb9f\xc2\xc4\x96}\xb1\xe5\x81\xb9e\xd7\xdc\xb2\x88\xba'\xa2>6\xa3\x16\xeb\x06b]\xa7\xea.\x93>\x0fB\xbd\xaaCD#\x0e\xd3v\xb9j\xb7p\\6H\x0bC\x857\xe8qC\x85\xdb\x1b\x94C\xc5\n\x8d\n\x034R,\x8a\x91b\xf1j@\x86\x0f\xc3P\xb1\xb0\xeb\x06\n4P\xaa4N`iU\xe5|!\xf4?\x1aj\x0dz[mD\xb4\xde\x950L,\x84\x0e\xc6#\xb8 w\xa5i\xc7\xdc\xb4h\x8f+a\x94\xa0\x8e\xb9h\xda<\xfa)H\xab\x91\x8ak&M\xb4\xc0\x95\xa0\x8d\xd4\x15\x17M\x9b\xc7N\x05\xe9N\x0d\xe9\xae\x99t\x91\x98\x81H\xa90LP_\xac\xa7\xd4\xa9\xa1\xb4\xae\xffER\x8eER\x84\x81\x80z[=)n\x0d)bS\x8e8:\xaex_N\xcd\x82\xf7\x9a\xccR\x8c#\x99\xe84D\xb3#\xc8V\x03\xec.\x90\xc9\x93\x18V\xf0,\xab\x01\xf2,\x98\x0f\xc1\x9b\xb8\xbd\x81\xe0M\x82\xd2\x9b\xa4\xd4\x87\x8c\x88_\xc1\xded\xf5j\xa0\xf5$\x08\x105\xdffQ\x7fG\xd2<\xe8\x92p\x99[b\x9dV\x96\x96\xa7\xdc\xd2\xf2\x14\xf6G\xb0r\x0c8\x1d\x11\xa7\xd3\x14\xa7k\xc0\xe9\x8a8\xdd\xa68=\x03NO\xc4\xe95\xc5\xe9\x0b89\x0c~S\x0c\xbd\xa1\xb0n\xd9\xa4J0\x14\x16 \x9bT\xe9\x0f\x85\xb5Dc\x15\xa2]\xcf\xe2$\x9c\x03\x9e\\\xe2\x13\xfd\xcbK`\xf3%\xd3\"\xe1\x14\xf6\x9b.\x14\x9a\xf3\x9a\xe6\xc9\xac1\xb9Y\xcc\xe7\xe6\xaf\x1c\xb2WB\x9f8\x9d[\x10v\x94 \xfc\xbc:\xb5`\xdei4\x1b_\xac\xe7[ed\x0de\x93\x07\xce\xd6B\x17&\xe4\x9b)k;9h\x96\xb5\x95j8\xd52G\x8d\xad2Y\x15\x11i\xf2\xb9\xbaF\\m#\nDE#\x8a\x14\xacc \xc05\x10\xe0i P4R\x10\xa0\xc8\x8b:\x06\xe2\\\x03q\x9e\x818_K\x9c\x82\x80\x828E\xae\xd21\x10\xee\x1a\x08\xf7\x0c\x84\xfb\x06\xc2{Z\xc2\x15\xc4\x15\x84+\xb2\x92\x8e\x81)\xd7\xc0\x94g`\xca70\xd530\x15h\x99R\x10^0\xa5\xc8i:\x06\x86]\x03\xc3\x9e\x81a\xdf\xc0p\xcf\xc0p``\xb8\xafe\xd8\xc4\x94\xa2\xcc50\xec\x19\x18\xf6\x0d\x0c\xf7\x0c\x0c\x07\x06\x86\xfb\x12\xc3%S\x03\x03\xe1\n\xa6<\x03S\xbe\x81\xa9\x9e\x81\xa9\xc0\xc0T_b\xaa$\xfc\xd8@\x9c\x82p\xdf@x\xcf@x` \xbc/\x11\xce\x0d\x16\x8aa\xc77P\xd73P\x17\x18\xa8\xebK\xd4q\x14\x98\x1c\x94f\xc9AGA_\xa2\x80k\xc5d\\\x8aV\xfaR+\x1c&\xd3J\x05\x8fN\x1a\xdf\xef\xb1R\xa1\x0d\x8a\xb6\x0f\xe7\x1aEF\x0dB\xbd\"\"C\xa1\x9e\x05\x93\x8e\x12J\x1b\xed\xa99\x8a\x93wQ\x9ai7\x87k)\xdft\xaa\xe7n\x8a\xc2\x9c?B4,B\xbfgq\x8a\xef\xd6Z\xac\xd6y\x04\x1bx\x0dm\xf7\xf5\x8fp\x00N\x07\x1f)\xc8\x96\x8b\x08\xde\x85\xf3u\x84\x0f\xbe\xfdx\xa88\xa1\xc4\xda\xd8\xb8\x16l<\x0b6\xbe\x05\x9b\xc0\x82M\xdf\x82\xcd\xc0\x82\x8d\xd3C\x056z\x8a\xfe8.\xf9\xdb\xc7\xf1\xa3\n\x17\x89\xd1\xf7\x10B\xd8t*\xc7\x85\xf8\x9e\xc7@\x1c\xa4\x19\xa1\x87a\xeb0b(\xaf\x19F\x1f\xc3\xd6a\xc4P~3\x8c\x01\x86\xd5b\xe4\xa1\x82\xbav T\xc1\xb4\x19e\xbf\x11J\x0c\xd5o\xc6\xca\x00\xc3\xd6a\xc4P\x83f\x18\x91*\xedm\x06\x0c%R\xd16\xd9\xa0\x89we\x06dO&\xbf\x19\xc8\x8c\xc9\xe91T\x1f\xccD2\xf0\x82\xa3\x1aE\xb3E\xec2\xa1\x8e\xdf\x9cR\x82\xcb\xb3\x1bR\xca\xc0K\x02j4IB/\x93\xea\x1e7'\x95\xe0\n\x9a\x92\xca\xc0K\x02jz\xdf\x95\xf0\xcb\xb4\xf6\xb6\xa0\x95\"s\xdc\xa6\xd4\x96\x15J\"\xea\xe8\xedKM|\x8c\xc22d\xfd\xc6\xf4\xb2\n\x92\xd2\x1eu\xe1\xe5u\x94\x94\x13~r\x0b\xc5%\xcd\xcad\xeby\x0e\xed\x1c\xb2<L\xf3\x0c\xc2\x1c;\xebN\xe9\xfas\x18\x11\xbc:\x8daL\xa1\x96\xec\xa2\x9a\x9e\xb9\xdc\x82\xbc\x11S\x08\xd0B~\x02av\n\xcc2\x01\xfe\x03\x13\x80=>&\xc1\xd1\x13\xf1\x87KaG\xc0\x9fB\x0f\xbc\x07'\xc2eD\xfc\xb9\x05\xd1\x13\x88\xf8\xa3\xa8\xf0\x1f\x9e\x8a\xfa\xfe\xf8\xc3-\xe3\x0f'\xa0\xf7\xc0\x04\xe0\x10\x9a\xea\xc2\x9fX\x0c\xdeCkc-\x05\x92=\xfc\x11$\xfc\xe1\xbd\xe0\xd8\x92\x10\xec\x07\x11\xc4=\xfc\xd3\x1fD\xc4\xf1\x83\x131(\xadsg\xa1\x7fv\nv\xceZ\x15\xc0<\x00 Mb\x87]\x00\x83\x08\x18T=\xf6\xa7\xa7\xa2\x89$\xfe\x0c\xe1\xfd\x1f\xef!\x82Jw\xfc\x01D\x0c\x1eN\x0c)\xed\x8b\x80\x1f\xb6p\x03\xf5\xdb6h>\x7f\xfc.\xdc~\xe3\x89>\xa7_.\x13\xa4\x16\xc9\x9c\xd6S2\x9dG:\x1a\xca\xf3\x86\x07l\x7fVy\x13\x8c#\xfet\xc5\x9f\x9e\xf8\xd3\x17\x7f\xf6\xc4\x9f\x81\xf8\xb3\xcf~b\xe2\x85{o*\xd4_E\xf9x\x12\xe7\x99\xe9\xd8\xa4|w\xce\xe5e\x16\xe5\xd2\xc3\xe9r\x9d\xe4\x05\xbf\xe2%\x87\xa4\x02\xec\x13 \xb2\x0erz\n=\x18\x8d(2\xfc\xb33,\x0f\xdf\x93\xe5.\xae\xf0\x02\xfde\x98\xf6\xc0\xde8\xcf:\xf8nS\xf2V\x0c\xda\xfc\x01wH\xd4\xd8iIt\x15\xe6\xdb\xaf\x06)\xb6,%\xcb\xe4.J\xf1\xf5V\xdc\xfe,\xe8B\x05wyB5\xec\x94Krk\xf5\x95\xc0\xed\x7f\x87Dg:\xb0/\xec\x0e\xc4w\xd2\x0f\x1f\xcb\xd7 Q2\x8c7\xc9P\x9cN\x05\xa7\xe2\xfe\xa0-\xf0\xb9\x15|\x8a\x0b\x83\xb6\xc0\xe7U\xf0)n\x08\xda\x02\x9f_\xc1\xa7\xb8\x12h\x0b|\xbd\n>iK\xe0\x96\xf8\x82\n>i\xbf\xe0\x96\xf8\xfa\x15|\xd2fB\x1e\xdfVN\x82x\xdb\x07s\x14\xc4=\x9c\xd03\xf5\xd2%\\\xa2\x0f9\x19\x81\xdb#\xdb\x80\xe3Kh\xeeb\xc8\xf5!\xd4\xc9\x18\x9cah\x15\xd4\x13\x82\x87\xf8~\xedh\x9eE\x04\x85\xd2\xc3\x91&\xf6\xc1A\xe3&\xaeR\xf8\xb3\x86\x0e\xed=\xf5|\x15\x8c\xf8\xe6\x97\xb6\xe7\xc2A\xa5\x12\xf5\x83\xdc{\x06\x9cN\xd5'\x16\xd7\xb7\x18\xfd\xe2\x15\xbb\x0fJ\xbe\xea)N\xb4n\xb1\x0b\xa5[\x9c\xc4 \xf1IT\x13\xf1-\x00\xfe\x10?w\xa4\xe7N@\x9e\xbb\xd2\xf3\x01y\xecq\x8f\x11\xfd\xe8\x99_<\x0b\x04\xd4=\xe99C\x1dH\xcf)\xea>\xf7\x98\xa1\x1e\x14\xcfz\x02\xeac\xe99C\xed\xd8R\x01\xc5\xed8\xdcs\x86\xdc)y\xf4E\x99xRA\x81\xde\x97\n\x18\xfa\x1e\xf7\xbc@_\xf2\xe9\x89\xe8\xfbRA\x81~ \x150\xf4\xc7\xdcs\x86\xde-Yu\x05\xf4\xae#\x15\x14]\xeaJ\x05\x14\xbd\xebq\xcf\x0b\xf4%\xab\x8e\x88\xbe'\x15\x14\xe8\x03\xa9\x80\xa1\xefs\xcf\x0b\xf4%\xab\xb6\x88\xfeX*`\xe8=[*`\x1a\xe9p\xcf\x89\xe7\xa4\xc6\xa4\xf4\x9a\xe1l\xb6}\x80\xd1h\x13\x0d\x7f\x83\xa1!\x86`\x1c\xec\xb3=|\xd5\xb0\xa1\xf1-tL\xd8\xfbl\xeb\\5d\xd8\x0e\x97[\xe0r/\xaa\xe1\xc2v\xb8\xbc\x02\x97wQ\x0d\x15\xb6\xc3\xe5\x17\xb8\xfc\x8bj\x98\xb0\x1d\xae^\x81\xeb\xa3\xee\x10d\x0el\x9fm\x17\xab\x86\x07\xdb\xe1\xea\x17\xb8j\xef\x15\x14pq\x97\x82\xe5\xcd\x8e\x0dT\xc7\xf1\x02\xc5\x08lx\xff\x1e\xf8\x07\xf48\x9a\x8c\x96;\xadP\\S6|\xac\xbd\xf0\xb0z\x97\xd3e\xba\\\x14\x17\x1e\x8f\xb36_\xa86H\xfe\xf2d\x14\xf5\xd3\xdb\xb1\xf0L\xae\x1c\xe1\xf07\xe1\xadmC\x0e\xca\xe1\xa1\xf0m8\xf8Mi!-\xc3\xaf\xb6\x13kw\xf8\xeanQ\x9dzE\xbb\xacNn\x8es\xe4w\xc6 \xf5\xbd\xa2>\xf5\xcd~Y\x9f^\xce70\xd5\xf7\x8b\xfat\x84(\xab\xb3\xfb\xeeL\xd5\xc9\xa5~\x0c\\\xf1\x82;\x1e8(\xda\xa2\xb0\\c\xe4\xd6=c[\xfd\xa2:\x1d\xbb\xdd\xb2:\xb9\xcc\xcf\x91_L(\xd4\x1f\x14\xf5Y\xf8P\xd6gw&\x9a\xea\x1f\x17\xf5idc\x17\xdbBR\xfe\xc6'\xeev/\xe1>0\xf2\x9c\x8f\xce\xe2D\xd6\xc6\xeaE\x9dLw\xcd\x97t\x92\xd8\xac\xc5oQ,u\xb8\xd4\xd3R\xe5J\xe5)\xd5\xc0\xae\xf4l\xd9me\x0f\x94\xb2,\xa5\xc2j\x92\xb4\x12\xbe\xe8\xef\xc4+\x12\x9de* \xd1\xf7fX\xfe\xc6\xf0o\x10\xfc\x9b\x13\x7f\x08o$pVe\x1e/&H\xcf\x06\xddx\xdf\xed\xbe\xe9\x1c\xb9\xc1\xb0\nE^\x1f\xc0\x81\xfdO\x05\x0cS\x8c\xb0]\xe0K\x89\x8bP\xba\xdd\x0e_y\xceA\x8c\xfb\xb5\x8d\xeaRE\xc0!6F\xcca\xfa d\xbd\xf0\x85^L\x12#\xee\xe5\x8c\xf8\x92/&\xad\xbdB\x82{\x85T\xf7\nI\xef\x15\xbd\xb0W\xf4\xcc\x1e\xeb\xad\x8etaW\x89W\xbe\x9c\x8bu\xb9\xe2~\xaeS\xed\x95_\xdcE\x88\x94\xab\xadu\x1a\x84$\x1bw\xad^Z\x18PyCc#\x03PY\xc0N\xf1w\x8a\xff\x1f\xaf\xf8\xd5\xb0\x05\xa9|\x9c\xe4*\x8d\xc7o\xa1\xe0\xd3\xcb,(\xa9\x04 f\xfd\xbe\xbf^\x7f2Y`\xe6\xd9{Zh\xac\xf8\xcd\xf7/\x7fio,H:R*\xb9\xbd\xc1\xfd\xd7N:4\x85\xaa\x96\xdcb=\x1f\xc7I\x12\xa5\xfc\xb1N\xc5\xc5Ja\xf5\x11\x978cop\x86\x89\xe2\xfe%\x0bfC\xe9\xd9\xda\xb6`\xedX\xb0v-X{\x16\xac}\x0b\xd6=\x0b\xd6\x81\x05\xeb\xbe\x05\xeb\x01W\x03\xb7\x96\x1f[\x90;\x16\xe4\xb6\x05\xb9kA\xeeY\x90\xfb\x16\xe4=\x0b\xf2\xc0\x82\x9c\xed\x06\x95\xa8\xfc\x01\x04\xf5\xb7\xe0\x85M\x9e|\xeb\xd8\xf8'>R\xba\xf1m\x1b\xc7Y\x04\x07/\xdb\x10\x1fO+\xf7'\x8be\x8e\xa1\xcc5\x94y\x862\xdfP\xd63\x94\x05\x86\xb2\xbe\xa1l`(;\xbe\xb0\x90\x0bP\x94M\x0cr\x99\x18\xe421\xc8eb\x90\xcb\xc4 \x97\x89A.\x13\x83\\&\x06\xb9L\x0cr\x99pr!\xa5G\xdd.\xbc:<<\x84\x10&0\xbd\x808\x83\x10\xb2\xebe\x9a_\x87 y=\x06*\xdd\x87\xf0\xe4\xa4\xe7\xa29\xe5\xc9\x89\x1b\xc0>LONlX,g\x90\x1c\x12L\xd0\x05XmT\x08\xb2\xf5\xa2\x1d\xbe\x8a/\xba\x93W\x9b\x83\xf8\xc2\x82xd\x1f\x1en:\\\xc5\x1f\x97x3u\x98\xc3\xab\x0d\xd8\xd5\xff!\xb7\xf4j\xd3}\xe1\xc0\xa6\xfb\xc2\xbe(j\x1e1>f \xe6E\x90\xaf\xec\x02\xe2\x97\x82\x82p+\x002\x00\\>\xd0\x95\xbb\xa4\xbc\xaf+\xf7Hy\xa0+\xf7IyOW\xde#\xe5\xbe\xae< \xe5\x9e\xae\x9c\x9e\x15wu\xe5\x03R\xee\xe8\xca\x8f\xe9YsvO\xecQW\xd0\x94\x99\x05\x81\xdf\x19\x16k\xc1G]x5\xd3\xf4\xcb\xeaXU\xc0j\xe6\xc70\x82\x19\xec\xc1\x0fC\x98\xe1LC\x11\xa0\xf0\x0d\"?\xa96\xd8\x99\x05^qr\x85\xd0\x91+[4\x92B\xaaO5jR\x88\x81oxjAydB\xdb\xf0T\xd7\xf0\x8a\x13\xc2LJ\xd10\xf5\xd3\xaa\xa7[\xa3\x9e^\x8dz\xfa5\xea\xd9\xabQ\xcf\xa0F=\xfb5\xea9\xa8Q\xcfc\xa6\x9e\xea\x0e\x0f\xbc\xa6rwl\xa8\x91\xfd\xdaV( \xe0;8\xd66t\xe1\x85\xad\xa0\x01\x0d\xf4zu\xec\xab\n\x90\xba8\"\xd9k[I\xf9\xc1\xdaF^\xac!\xfd\xb9Mo\x07\xf9\x81] \"\xd1\xef\xa8\xccIK\xff\x94\xa7_O&!\xd2\x81\xdc\xde\x8eZ\xe6(\xaa\x08!o\x84\x84\x19\xea\xbe\xd2P\xb5\xfe\xcc\xa91dWdyk\x02W\x8e\xd9\xa0\xdd\x1a\x83\xf6j\x0c\xda\xaf1\xe8^\x8dA\x075\x06\xdd\xaf1\xe8A\x8dA\x1f3\x83nf\xb0f\xf9:\xd0D\xc6kGo\xb8\x8e\xd6p\x9d{\x19\xaeD\xfe\xdaQrp\xb0v\xba/\xecm\xf9\xc8\x1d\xbd\x01;Z\x03\xd6\xf21\xad\x8e\x87*r \xb1\x0e\xe4\xce\xfd\xa8.G|\x191bh\x0bdf\x83\xd6\x8e\x10N\x8d\xc1\xbb\xdb\x1a\xfc}\x18Y\xb9\xb5\x86\xef\xd5\x18\xbe_c\xf8\xbd\x1a\xc3\x0fj\x0c\xbf_c\xf8\x83\x1a\xc3?f\x86\xdf\xd4\xb0k\xe4\x88$\xd6P\x96kWo\xe0\xae\xd6\xc0\xddOb\xe0\xae\x92\x93\x83\xb5\x8bM\xe5~\xfc\xe4\xae\xde\xd0]\xad\xa1k\xf9Q\x19\xba\x82lB\xb4\x03\xb9\xfbq\xd4\xf3!\xbe\xd8\x00b\xec\x1eH\xcd\x86\xaf\x1di\x9c\x1a\xc7\xe0\xd68\x06\xaf\xc61(\x14\xfa\x9e\x0c\xaf\xbc&\x0e\xc2\xafq\x10\xbd\x1a\x07\x11\xd48\x88~\x8d\x83\x18\xd48\x88c\xe6 \x9a;\x80:yy\xb0\x9d\xcc\xd6\x9e\xde\x11xZG\xe05r\x04\xd2\xc4v\xaa\x9c\xd8\xae=%_\x07k\x0f\x1b\xd4\xc7q\x97{z\xb7\xe0i\xdd\x82\x96;\xe4\x16\x8e%\xb7\xa0 \x9f\x10\xef@\xee}\x1a.\xc4\x0c\x00\xdf\x10b\xf0#\x90\x9b\xdd\x84v\xdcrj\xdc\x88[\xe3F\xbc\x1a7\xe2\xdf\xc7\x8d\xdc_0+\xbf\xa1;\xe9\xd5\xb8\x93\xa0\xc6\x9d\xf4k\xdc\xc9\xa0\xc6\x9d\x1c3w\xa2q\x17\x8a\xb8\xab\x81\\|\xb8\x87l\xd6\xbe\xdem\xf8Z\xb7\xe1\x9b\xdcF\xb0\x9d\xdb\xf0\x95\xfc\x1d\xac}lp\x9f\x86\xcb\xdc\xd7\xbb\x0f_\xeb>\xb4\\\xaa\xdc\x87\x82\x0d\xc2\x84\x03\xb9\xffi\xb9\x91\x13\x89e\x83\x88\xd1O\xd0\x88\xd9\x9dhGA\xa7\xc6\xdd\xb85\xee\xc6\xabq7~\x8d\xbb\xe9\xdd\xcf\xdd|\x94\x00W\xbd\xe6n'\xa8q;\xfd\x1a\xb73\xa8q;\xc7\xcc\xedl\xe7V\xea\xf9\xef\xc1}e\xb0\xee\xe9\xddKO\xeb^z\x9f\xd0\xbd\xf4\x94|\x1e\xac{\xd8 ?-\xb7yO\xeffzZ7\xa3\xe5V\xe5f\x14\xec\x10f\x1c\xc8{\x0f\xc3Uu\xdd\x825\x8c\x18\xfe\x84\x8d\x99\xdd\x8ev4uj\xdc\x92[\xe3\x96\xbc\x1a\xb7\xe4\xd7\xb8\xa5^\x8d[\n\xee\xeb\x96>V\xd0\xab`+\xf7\xd4\xafqO\x83\x1a\xf7t\xcc\xdc\x93\xc6\xfd8\x1f\xc1g\x00\x1f\xc5\xeb:\xd0\xbb\xa1@\xeb\x86\x02\x93\x1b\xeam\xe7\x86\x02%\xbf\x07\xeb\x00\x1b\xec\xc3p\x9d\x07zw\x14h\xdd\x91\x96k\x95;R\xb0E\x98r \x0f\x1e\x96\xbb\xaa\x161\x02\x10\xe3\x0f\xd0\xa8\xd9=iGe\xa7\xc6}\xb95\xee\xcb\xabq_~\x8d\xfb\xea\xd5\xb8\xaf\xa0\xc6}\xf5%\xf7U\xa3\xef\xb4\x8c\x9eU#\xef5\x1d\xe0c\xd9\xfd\xa7\xf4z\x93~\xb91\xf8A:q\xd5\xdf\xd6\xf5\x0dj\\\xdf1s}jg\xd0\x1b|\x1c?}\xf8x\x9e\xd6}\xbd\x8b\xebk]\\\xdf\xe4\xe2\xdc\x86.N\xdb\xe5N\x1f\xbf\x99\xf7\xa9\xfb\xac\xd2\xe5\xeb\xbeRJ\x07\xeb>v\x19\x0f+\xab\xbc\xafw\x8c}\xadc\xd4\xcaJ\x95dV\xb0G\x98s \xef\x7f\x1e.U\xbaH\x08A\x02x\xc0\xc6\xcd\x8eR\x1b?85\x8e\xd4\xadq\xa4^\x8d#\xf5k\x1ci\xaf\xc6\x91\x065\x8e\xb4_\xe3H\x07\x1f\xefH\x8f\x89\xff\xfc\x868T{`v\xa4\x9f\xa6\xb3W\x83zU\xab8\xd4c\xe6P5\x0e\xb3\xff\xd1t\x0f\xe0\x13\xd1\xbe\x1e\xe8\x1d\xe7@\xeb8\x07&\xc7\xe9|\x84\xe3\xc4]\xec\x04\xcf\xbe!\x8e\xb3\xd2\xc5\xeb\x81RZ\x07\xeb\x01v)\x0f/3BLJO\x0ez\n\x11\xa4x+\xa7\x1b\xdc\x97\xf0\xf4a\x08'd\x93C\x8a\xbe\x92l\xff\xfed\xa7\x0fL69\x0f\xd9S\x92\xdd\xbb'\xd9\xe9\xc3\x93M\x8e^\xaa6+\xa6xo\xee\xd6d\xa7\x9f\x85lr\xca\xb3\xaf$\xbb\xbf5\xd9\xe9\xc3\x93\xcd\x08\xc7\xc7\x104\x91\xcd@\x17\xd9\xa4x\xbbs\xf3I\x9f\x8a\xd9}\xc2\xac\x03\xe9\xe0\xf3q\xad\x1f@\x08I\x90\x0e>\x17\x19S4\xdc\xa3q\x04\x0d\x18\xb0\x0f\xf9\xb1Z\x98~\xcf<\xf2\xa1\x18x\x86\xc5\xf7\xd9HO\xc9\x91\x15\xa45\xed\x1f\xe0\xf4\x14\xd0\x10E\x95\xc7\xa5\xca\x83\xf8j\xbfp\xc8\x19S\xa5\n\xe1]\xf1\xaeF\x85\xfc\xc0\xccuz\xbc\xdfnc\xc6\x9d\x93\x13\xbfsr\xe2\xba\x9d\xcf-\x06\x15e\x98\"L\xdd\xf4\x0f\xa3\xa9l\xfd35L\x9a\x9e\xa1?H+P\xc7\xdbD-\x90^\xab\xa2!\x14\xd1 =\xdc\x80\xe6\xd9\xc1\xb4\xfb\xc2>=\xf5?%\xe9D\x9d\xb14\xea\xb7\xcb\xa7\xf8\x14\x8b>\x8a\xb3\xb7\xe3h\x7f\x06\xa9\xfdPL\xcd\x88{\x99R3,zC\xe5\xceQox\x12S$\xc4\x9c\x91\x10\xd3!\xb3\x07|0\xea\x9bgb\x80Y\xc7'\xee6\xe7\xf4\xd4\x7f@f \x1d\x9a\xf6!\xfd\xa4\xcaN4\xc6i\xaa1\x8eIc\\y\xe7\x9c u\x9fH]\x16\xb7\x92M\xa4K\xce\x03pJ\xd5(w\xeb\x18\xd0\xd2\xf6@\x84\xa5\xe4\xf0\xe5L)t\xf7\xa2\x11i\xa9\xfb\xe9i\xd3\x9c9-ON\x9e\xef\xceN\xee\xceNV\xcbvg'\xd5e\xbb\xb3\x93b\xb2swv\xb2\xf4\xea\xd2`\xb4;;\xb9;;\xb9;;\xa9T\xc7\xdd\xd9I-\xb5\xccQT\x11\x96\xb3d#\x12f\xa8\xbb\xb3\x93*\x83\xdd\x9d\x9d\xdc\x9d\x9d\xdc\x9d\x9d\xccwg'e\xc3\xde\x9d\x9d\xdc\xce\xc0wg'M\xf9w\xb1\x019\xcb\xdd\x10\xa9\xd9\xf0wg'E\x07\xb0;;\xb9;;\xc9\xbb\x85\xdd\xd9I\xf3\xb8\xb5;;it\x17\xbb\xb3\x93\xbb\xb3\x93\x8d\xdd\xc7\xee\xec\xe4\xee\xecd\x8d\xdb\xd9\x9d\x9d\xdc\x9d\x9dT\xb8\x99\xdd\xd9\xc9Fngwvr[A\xd7\xed\xa3\xd8\x9d\x9d\xdc\x9d\x9d\xac\xba\xa3\xdd\xd9\xc9{\xb9\xa7\xdd\xd9IAcvg'\xb7\xe0\xa7v\x8bW\x03\x9evg'\x9b\xcbjwv\xf2\xe3\x8e\xd3\xed\xceN\xaa\xcawg'+\x0eswv\xf2~]\xbc;;\xf9\x00\x84\xc3\xee\xec\xe4\xee\xecd3\xb2wg'M\x93\xbe\xdd\xd9\xc9*\x19\xbb\xb3\x93\xbb\xb3\x93\x0fCS\xddi\xb6O\xde0izwvrwvrwvR\xd6\x98\xdd\xd9\xc9\x87!\xec\xcf\x7fvr\x11-\xb2(?o\xe3\x1f\xddY\x94\xe5\xe4\xdd\x9c\xef\xc2\xb9\x05Y|\x17\x8ds\x98GI\x87\xbe?\\zE\xed*O\x11{QF^\xa5zs\x1d\xcf#h\xcf\xa3\xe4\xe0\x00N\xf1\xcb-\x11k\x08l\x7f\x1f\x1f\xaf\xe1\xabw\xde\x85s\xe9\xa5\xb9\xca\xe3\x9c\xfa\x17\xe6J\xcfC\xcds\xfd\xa9N\xf1\xd5\xee!\xffF\xd0\x93\x11\xe0\xe4\x97\x082Q\x82(\xdf\x0d\x1a\xea\x8b&U\xc4)|1\x82I\xb5\n\xf7\"\xd0\xf4\xe04\xb1\xf0[\xba-\x98\x1c\x9c&\x1d\xfa\xe6{\xf9-\xa6-\xf9\x15\xa6\xb6\x96\x90\xf2\xfd\xa5\xba\x83\xb45/om\xb17\xb7v\xc9\xab[[\xec\xbd\xad\xc2oW\xfa\xedI\xbf}\xe9wO\xfa\x1dH\xbf\xfb\xd2\xef\x81\xf4\xfb\xb8\xf8-K\x88\x07\xdbVDZ\x1d-0\x8do\xa2\xf0\xf7\xaa\xc0\x84\x03\xc4\xe4\xe8\xaf\xcd^I\x8b\xc6j|\n\x80\n\xce\x02\xbcU\x98\x8a\xcd\";\x04\xa9\xd0,\xb2\xe1\x87\x8a\xcc\"8\x8b\x7fx\x95\x9e\x8a\xcf\"\x8bdTx\x16\xc9\x0cS\xd1Y\x90\x0f\xcaW\xe3Z\x80O\xe1Q\xb1q\x87?\xe1E4[O#T\x1c\xe6\x90_G\x90\xe5a\x9aC\xb6D?\xd2\x08n\xe2\xf9\x1c&\x11*],\xb3\x1cB\xc8\xe2\xe4j\x1e\xc14L\xd3[\xb8L\x97\x0b\\\xed2N\xb3\x1cVa\x96\x95\xb9)&\x87\x0d\x9a\x8f\x1e\x937\xde\x0f\xd1\xb7=4\xa4\xd8\xecm\xcb<9/ETQ\x92\xad\xd3(\xc3-\x94\xdd\x1bg\xe0X\xf8Xj\x91\x13\xb7\xd1\xc8\xb0\x81.{}\xf2\x10\x89{\x7f\x04\xed\x0d\x8a\xfa\x8b1\x8f>\xccm\xfav\xe5!\xaa\xb97R\xbc\xef?w \xa4SB:\x1aH\x8f@\xba%\xa4\xab\x81\xf4 \xa4WBz\x1a\xc8\x1e\x81\xf4KH_\x03\x19\x10\xc8^ \xd9\xd3@\xf6 dPB\x06\x1a\xc8\x01\x81\xec\x97\x90}\x0d\xe41\x81\x1c\x94\x90\x83*d\xd1\xbb\xa8\xcb\xa2\xcd4Z\xe5\xf8\\p\x08\xabe\x96\xc5\x93B\x9b\xc2\x1c&q\x0e\xae\x0b\xcbK\x84\xbb\x1d\x1fF\x87\xe4Q/\xc0\xcf\xb0zD\xf3\x19D\xf3h\x11%yG\x9d\x8e\xa4\xda\xe6\x91\x97/\x17$\xa4\xc5\x0b\xa8s{\xc8\xbd|:w\x86\xdc\x0b\xa8sw\xc8\xbd\x84:\xf7\x86\xdc\x8b\xa8\x8b\xdc[Z\xbc\x91:\xef\x0d\xb9\xb7R\xe7\xc1\x90{3u\xde\x1fro\xa7\xce\x07C\xee\x0d\xd5x\x92] S\xbd\xa4zkg\x9e\xbdM\x9b\xbdO\xfaA/;\xb0\xe9\x85\x07\xbb\xcb\x0eTe\x0f{\xd9\x013\xb5\xcfx\xa8?\xfcl\x87\xfaq/w\xdd\x0et!\xd4-w\xe3\xdef0\x9a\xd5:\xdc\xeb\x0cF\xb3b\x87{\x9f\xc1hV\xed\xb0\x160\x98\xde\xee =\x12\xc3g>H/t\xb7^%\xdc\x06*\xe15P \xbfN%\xe8Bl\xa8\xdf\x1e\xbf;\xd8\xceGm\xff\xf5\x07\xdb\x05\x9f\xa6\xbc\x0d\xe1\xe1\x0f\xaf\x0b\x06\xa27\"\xaf\x81\x11\xf9\x0d\x8c\xa8\xc7\x19Q3#1\xf3+\xed\xcf\xd5\xf0\xbc;L\xdex\xfb\xcf\x7f\xdcar\xc1\x88\xcc\x07\xca\xb71\xb2\xfb\x10[\xbb\xbdD0$\xbd\xb1\xf9\x0d\x8c\xadWglt\xdb\xcf6\x86V\xc3\xb3[\xdd\x0f\xaf\xe3{w\xb8\xfb\xbf\xefp\xb7`\x88\x9a\xbdhB\xc8\xa6\xbcN\xe4\xf3\x1f\xd2\x16\x0cNo\x94\xbd\x06F\x19pF\xd9\xdc\xe8\xeax\xd3\x9cE\xd1\xf2\xb7;P]5\xc5\xff\xee\x03\xd5\x82ij\xb6\x91\n\xa6i>X\xbd\xad\xe9\xde\x9f\xc1\x86\xdb6\x05\xf3\xd4\x9bpPg\xc2t+\xac\xc1|w\x07\x9cw\x07\x9c\x0d\xdc\xc8 \x9e\xb2\xc1\xad\xcf\xe7nq\xc0Y0o\xcd.r\xc1\xbc\xf5.\xc0\xe5\\\xc0v&\xfeQ\xcc6\xdf\xa1-\x98\xb1\xde\xd4\xfb\x9c\xa9og\xca\xf5|\xdc\xef\x8c(\xec\x0e\x15\xef\x0e\x15o\xd3X\xbd\xa9\xebS\xd3N\x03w\xe0\xd6\xb9\x03z0\xe5>\xae\xe0c\x85R\xb7\x19H\x96I\xbf\xce%\xd0C,\x06w\xb0;\xe4\xab\xb0\xa4\x87<\x06\xbb;\xe4\xfbI\x1b\xadw\x17\xfa\xac\xac\xd3\xc0\xa5\xb8\x0d\\\x8a\xc7\xb9\x94f\xfaG\xcb\xfe\x93\x0e\xdd\xe2\xf5\xd8\xd2\xdd\xa8\x0dpw\xb0V\xdd\xad\xbb\x83\xb5<{\xff\xdd\x07k\x05\xe7\xa4O\xaa9\x0d\x1c\x98\xdb\xc0\x81yu\x0e\x8c\x1e\xb4\xfd8\xe7\xf5\x9fu\xd0\xd5\xe0\xc0v\x07]\x8d]\xbc;\xe8\xfa\x00\x84\xc3\xee\xa0\xeb\xee\xa0k3\xb2w\x07]M\x13\x9f\xddA\xd7*\x19\xbb\x83\xae\xbb\x83\xae\x0fCS\xdd\xd1\xc3O\xde0izw\xd0uw\xd0uw\xd0U\xd6\x98\xddA\xd7\x87!\xec\xcf\x7f\xd0U<\xb1\x17]\x85y\xb4\xcd\xc1\xd28\xc9a\x81\x0f\xc7(4D>8\xba`\xbc\xea\x0f\x86\x82p\xe8\x88\x9cpy\xea>\xfb\xf59t\xc1E^b\x01\xfb\xe0t\xe0\x00\x1f\xf8,7\xcf\x97G\x93\xe8\xa9\x98o\xb4u\x1c\xa1\x8e{!\x9e\xa4Q\xd7q\x85:^\xa3:\x9eP\xc7oT\xc7\x17\xea\xf4\x1a\xd5\xe9 u\x82Fu\x02\xa1N\xbfQ\x9d\xbePg\xd0\xa8\xce@\xa8sL\xea\x14\xe7\x18\xd5u\x8e\xb9:\xfc!/\x0c\xc5\xa1\x93\xcf\xa9j\x15k\x9b\xa3\xaa\xbbS\xaa\xcdO\xa9.\x86\xd2\x83\xdd\xb1UX\x007\x0c59\xbe\n\x0b\xf4\xa4\xc8759\xc7J\xab\xb0\\O\x93\x03\xad\xb4\n\xcb\xb349\xd9J\xab\xb0x\xa1\xc9\x11WZ\x85\xe5\x17\x9a\x9cu\xa5U\x06\x7f\xa6C\xafG]x\"\x9b\xc5e\x9c\x84sH\x91U\xe5\xf12A\xaa\x99D\xd1,\x9a\x0daz\x1dM\x7f\x87\x984\xfb.\x9c\xaf\xb1\xe2\x9e\x8e82\xa6\xd7a\x1aN\xf3(\x8d3\xe4\x7f\x181\xc8^\x18\x11n\x07\xdeC\x1b\xfd\x1a F\xd3A\xd3\xd7\x05yX\x88\xadSz\x8f=T\xc9\x81}\x1c\x89\xfd\xfa\x1c\xf6\xd1o\x1b\xff\xc6\x06\xd2\xa1\xc2\xef\xc0\xa9\x80Adw\xb5\x9a\xdfRzE>\xdb\xa8\x07\xf0\xe0\x1f&\xf9A\x1e/\"\x98D\xd7\xe1\xbbx\xb9N-\xb8\x89`\xb6\x848\x87p~\x13\xdef\x9d\xff\x18;mn\x9f\xcd\xcd\xb2\xb9567\xc2\xe6\xb6\xd7\xdc\xe4\xb8~\xff\x1e\xdb\xcf,\x9e%_\xe5\xd4\xb8\xf2%3\xaep\x9eF\xe1\xec\xd6Bz\x91\xa0N\xce\xae\x97\xeb\xf9\x0c\xae\xc3w\x11\x84\x97y\x94B\x98\xdcV4\xc6di.\xd2\xe3\x8d\xa0z?\x84\xd9\xef\xb0\xbc$\xd6S\x18\xfab=\xcf\xe3\xd5<B\xd6\xec\xbeFf\xcd\x8dH\xea\xf6\xf4\xc3\xcd\x7f\xd8!v9\xb6ix\xb8\xfd\xa8\xdb\x85\xa7\xcb\xe4]\x94\"\xb7%\xb8?\xd4\xa9!x\xee\xc1\xe46\x8f`\x12_A\x94\xcc\xe20!\xde\xea\x10^Do\xd71\x1b~\xe3d\xb5\xc65&\x11pt 1k\xc3\xa7\xab(\x1fO<\xf7\xbc-\xdd\x83\xa3\x9d8\x14A\x15\x9a?\xc4C\x85\xc6\x84\xbc\x14\xea\xe7\x0d\xa4\x1c9\xabv<\xb2\x87\x10\x9fx\xee\x10\xe2\xfd\xfd\xa2%\xd6\xda\x9b\xa1\xf8{\xca\x85\x8f\x05\x8e7\x08\xc7\x9b\x13\x7f\x08o$\x14\xac\xda<^L\x90\xfb\x1et\xe3}\xb7\xfb\xa6sT\xcc\xacy\xa8\xec:\xbe\xccy\xb0\xff\xa9\x80M\xe1\xfd\x08\xda\x98\xdfW\x08\xe9\x05\xb2\x14\\\x0f\xb9~{\xe3u\x90\xc7l\xa3@\xf9M\x87\xab\xfb\xa1\xfc\x9a\xbe\xf2\x9c\x83\x18i\xd7\x94\x02|\xa8\x0bx\xb3\xb7i\xf3i^\xe3;\x81\x9a^\xf8\xc3]\xbb\x90\x16\xb7\xf7t>\xe5\xbd=\xaa\xd9m8\x9bm\xc934\x9e\xab\xee\x8f4\x13RVP\x99u\xb2\x82\xca\xd4\x92\x15T\xe6\x8f\xac\xa02Id\x05\x95\x99 +\xa8L\xf7XAeN\xc7\n*\x137V\xa0\x9e\x9d\x91\xd2\xe2\xb7\xc6\x935\x9c\xa5\xa9{N\xd5u\xe31\x0bM\xf4\xfdw\xd4\xd5\xf5`\x91\xa4\xd9\xf5\xe1\xf6}\xa8\x11kJ\xc4\xca;\x9fX\xea\x9dq\x9c\x8d\x97\xc8\x14k\x0c\xefc\x86\x03Ly\x94\xaf\xd3\x84u)\xecag\x82 \xabP4]\xac\xc6\xef\xc2\xaaG\x0cM*F\xafJ\xe3G02\xfe\xc0\x08\x8e\x87\x10\xa3)\x00\x1a\x89\x0e\x0e\xc41\xe8\x12\x88\xb3\x8f/\xe0\x14_X\xf6*\xbe\xa8\x0c1\x94xG\xed\xf0y\x1c'u8\x0e\x14H>\x08\"\xb2\x89`\xb4\x83E\x9c\xbc\xfbH\xc7y\x0e\x1b\xd7\x82\x8dg\xc1&\xb0`sl\xc1\xc6q,\xd8\xb8\xe8\xa9\xef[\xb0\x19\x0c\xd0\xb3~\x80\x1f\xda\xf8\xafg\x95\x0b\x01l\xe4f\xcaG2\x08\x938 \xd3[H\xa3U\x1aeQ\x82\xe8_&(fl\xaf\xe0\x00\xdc\x0e\\\x87\x19\xf4`2_N\x7f\xcf\xd0s'\xb3\xe0&\xce\xafa\x1e%W\xf9u\x06qBe\xd3\x05\xf8\x178\x16\xb8\x16\xb8\xf8?\x0f>\x1c\xc2\xafY\x04a\x02\xe1l\x16c\xd4\xd3\xeb0NPp4\x0d\xe7\xd3\xf5<\xcc#p_'p\x00\x0e\xee\xfb(\x9c^\x93\xd6\xbe.\xd1\xe2\xbc\x10\xb95\xc7\x82\xc0\x82c\x0b\x10\xef\xaf\\\xf4\x08\xf1\x8eX\xc7\x9cc\xc6_\xb9nq\x90\xac\\\xb6\xaa\x0e\xde{H\xa2\xa1\xd2\x14\xf0\xe5\x80\xb8\xbc\x04\xd2\xa3\xf10\x98 \x11\x86\xf0\x04D\x9b\x00F\xb0\xf1x\xbd\xa71\x93W\x8d\x99T\xad\x06\x08g1\x0f\xfc\xa0o\x9c\x00b\n\xb8\xe6\x8fQ\xf3\xc1\xfd\x9b?F\x08\x8f\x1b4O\x00\xe5\xe6\x1d\x07\xb5\x7f\xach\xdfm\xd6>\xd2\x00\xf4\xb7\x01\x05\x0c\xb4\xe8&J\x03\x9aM!J\x14D8N3*\\\xa2\"n\x03*\x18hI6%\xc3\xf7\x11\x19\xae\xab\x92ECa #@\x7f\x1b\x90\xc1@K\xba)\x19\x83\x01\"\xc3\xf7\x15d\xf8\x8a0^E\x06\xb2C\xf4\xb7\x01\x19\x0c\xb4\xa4\x9b)F\x1f\x1b\xc6`\xa0\xa0c0hF\x07\xf6\x05\xf8\xa3\x01%%pI|\xa1 6\xd6\x90\xbe\xcaN\x9a\n\x05\xfb$\xfc\xd1\x80\x98\x12\xb8\"\x18\xe4P\xb1\x9e\xd8\xf77Z<$\xe0\x8fF\xb40`\xc9x\x8b\xec3\xc9#d\xeby\x0eqF\xb2\x1ca\x96E\x8b\xc9<\x9a\xc1:\x8b\x93+\x08!\x9b\xc73\xf4\xed&Nf\xcb\x1bX\xbe\x8bR<M&c\xca!\xe7\xa2\xf1B\x00jOe \xcd8\xcc\x91\x91\xe7\x0d\x9c\x02\x05\x14\xad\x97o\xb0\xf7@\xed\x85\xaa\xc6\x1e\x909Us\xcd\xbcJ\xd3\xe6R\x0b\xc2\x02\xd2\x18\xb7\x16\x01h6\xce\x97\xe3\xbb(]*\x83F\xe5\x8a\x91\xe9\x86?\x0b\xf2\x81U\xee\xac*j\xdd\xd9\x16\xdc9\xf2\xd3M\xa1\xc8\xfc:\x14\x85\xfa\x03\x96\x83\x84E\x9f\x8a\x8d}\x82\x15\x1e\x0e\xe7\x9d\x0dy\x1a\xa2X\x8e[\x14H\xc3\x1b\x9av_^\x02\x16Y\x1d\xd0\xdf\x8a\xd6\xeel\x9c\x15$\x89\x16)\x97z\x87\xec\xf9\xce\x86\xd7\x98\x12[\xa4\xe4Y\x98\xe5,|^\x85\xf95K\x8eN\xc3|zM\x99|\xb3L\xe3\xfc\x1658\x0d\xb3\xa8\x94\x18\x8a\xde\xdbw6|1\x02\x9b&\xf8\xef\x1c\xfc\x8b\xcf\xcf\xf3\xea\xcd\xc5\xe9T\x97\xa9\xb0\xb8\xb5G\xa6\x01\xdc\x02${\xc4\xadB\xb2G\xdcR${\xc4\xad@\xb2G\xdc2${\xc4\xadE\xb2G\xdc\x82d\xa9\x9b\x8al,\x94 \xffr\x15@x\\\xae\x03\x14\xcc\xd4&\xfdQ\x17\xbd'\xc9\xdc;\\\x98;\xb8\xcb|{\xab\x15\x01\x86\xc6-\xd0l\xb5\x8aGk{E\xed\xad\x16\xf4hm\xbf\xa8\xbd\xd5\xda\x1e\xad\xdd+jo\xb5\xccGk\x07E\xed\xadV\xfch\xed~Q{\xab\xc5?Z{P\xd4faS\xa3\x7f\xb4\xf6qQ\xfb\x98\xd8\xeaS\xba!\xe9\xcf\xb4\xa6H-\x18\x99=.\x80\xf7\xd8\xe8\xa5e=m\x82\"z\xbb\x0e\xe7d\xb4\xd9\xea\x8a\xf7\x89f6\x9e\x84\xc3\xea\xe3b\xfb\xcf^\x12\xe2A\xd1QN\nq\x1a\x15\x83LX9\xe5\xae\xd1h\xb9\x97\x84\xf2H\xab\xcc8\xa8\xc7\xd6\xad\xb2\x0e$q\x91\xd2\xa8E\x93[\x9c\xce#U\xe6G\xb9B\x11\x8a\xd9i\xbb|\xac\\\xb1\xe1\x97#\x1c\xbb\xba\x1c\xc1R8#\xde\xb3\x1bC\x90\xecm\x9a\x7f\x02\xc1\xfc\x01\xe9\x98}p:G>N\xc8xM\x132\xc0\xf22\x9f>)S\xfc\xeb\x028\xf7N\xcf\x80\xf4o\x97\xaf\xd9\xe5kv\xf9\x1a\x9e\x8c]\xbeF\xd6\x8e]\xbeFG\xcb\x7fs\xbe&x\xb8\xf6\x94#\x85\x12_\x15\"-\xca\x8b\xbex\x8a\xb7\xbb\xe1K\xeaC\xc8\xde\xae\xc34\x82t\xb9\xcc\xe1&\xcc \x9c\xe6\xebp>\xbf-\x87\xe2\x99yPD\x14\xa4\xa60\x92\x8b|\xcb\x04\x949x\xcc\x97\xe3,_\xa6\xe1\x95\xb4\x9b\xb7x\xda$\\\xaa_}d\xcb\xc6\xc5\xaa1\xbcg\xcb\xc4hv[l\xf4`\xab\xc8\xc5\"2\x9a \x04\x0c\xd8%\xc06\x0f\xec\x16\xc0.\x06v\\\x06\xedahG\xd8\x8e\xe4\x15\xd0\x1e\x81\x1e0h\x1fC\x0fx`\xbf\x00\xf61\xb0\xeb3\xe0\x1e!\x84\xfd\x0c\xc8O\xa1r\xaf\xa8\x1c\xe0\xcaE\xdd>\x01vy\xe0\xa0\x00\xee\x13\xb2l\x06= L\x08\xf2\xe9\x17\xd0\x03\x02]\x08\xe8\x98@\xdb\xb5\xdd~\x99.\x17\xea\x8eg\x9b\x05\xae\xe6\xcbI8W\xf4<\xa7\x19\xa5\x06T\xfbW\x95%\x92z\xd7&R\x0d\xf0fNN\x1b\x82\x8eX\xbb\xa3\xeeo\xa2\x1c\xae]V'\xfa\xe1\xb8\xa6\xfa\x9e\xac/~Y\x9fj\xcc\xc0T\xdf\x974hPV'*\xe4\xfa\xa6\xeaX-\xda\xbcRu\xf4\xa2\nd\x05\xe4\x1a#*hl\xab\xd4\x93\xde\x05\xddRXT\x0f\xa8\xa6\x98\xea\x0f$\x15v\xb8\x9e\xeaS\xbd4\xd5?\xaehu9\xc5o\xbe\x9d\xaf\xe1a\x84\xe6\xe9\xe5\xdd\x81\x84\xdd\x81\x84\xdd\x81\x84\xdd\x81\x84\xff'\x0e$\xc4\x97\xd0\xde\x08\xa10\xb12\xb3\x85mge\xdbY\x1a4\xb46\x0e\xba\x81\xa5q\xd0\x0d\x8c\x8c\x83n`_\x1ct\x03\xd3\xe2\xa0\x1bX\x15\x07\xdd\xc0\xa0X\xaf\xc2\xc3\x1f9\x80\x86\xc7\x0e\xe0\x13\x1f=\xa0\xa2P.x}\xe0\xc2\x83\xff\x82S\x08\xca\xc4\xf5\x15\xde\xf3\x19'\x97q\x12\xe7\xb7\xd5%\x0c)\xf0\x06a\xf3&\xab\xd6\xa0\x85w\xe1<\x9e\xa9WI\xaeL\xc9\xf0[\x9a\x0cg\xbb\xe7\xe9\xf6J\xd6r\xcdR,\xd5\xa6\xdb\xd78\xbf\xf7\xda\x83}\xe8\x17\xaa\xa1\x98\xf2\xa2\xd6\xf6\xc2\x83\xd3[\xc3\xc4\x1c\xa7p\xc3\x83\xd3Mg\x08\n )\xcfK!U\xd8\xa2\x9c\xbc\xacvojA_ B\x96s0\x9a\xa9\x12@~\x8d+M\xce@\x83 ;f\x95\x80\x1bB\xde+\xbc\xf2\xc4\x07\xba\xba9\xba\xd4\x8b\xdd\x14F\xd0U/e\xc9D\xa7:\x81\x17\x8b^\x08\xc2\x02\xfaQ\xd9\x0dR\xa5Y7\xdf\xbc\xaa\x9bo^U\xe7\x9b\xad\xa3\xee*\x8d\x93\xfc\xb2\xfd\x97\xab\x08\x9e\xc2\xff\xac\xe7\xf8\xbf\x7f&\x7f\xc1\x87#6\x87$\xb6Gj\x83\xbf\x92m\xd6-\xc3\x04\x181\xb2\xe1t\xa3\x0e\xf6\x96\xd3J\x8e\x9c\x92\x16\x81\xa6\xb4\xa4)e4\x19)MK{\xa2\xeb][Hw\x9c5R\x0e\xe54^\xcf\xf68\xab\x08\xa9Q\x85[\xc9~\xb7e\x0d\x19\xe5\xe6\xb6\x89\xbe\xe3 \xdfF\xf3\xfc\x96\xcfTH\x04\xd0\xa7(\x9e\xebn\xca\xdf\xa8\xb8+{\xd2\n\x81o0\x85\xb2R\xbf\xa95\xc9\x16m\x11 \x93\x9e\xdb\xb9%?o\x87\x15\x0d\x10={K\xe3\xb5\xd2\x83\xd3;\x851\xca\xce\xffM\xdd\xf8\xf2F\xcc\xecl=\xb8\xe0.\xabl\xf7\xaa\xeb6\x84f9\x9b\xd5,\xc1N5\xfd%\x8a\xa4XBT\xebi9\"l\x84\xa4\xafZ54\xd2\xae\x19#\xa6\x853g\x83\xe4\x172\x8dtq\x9aY\xc9\xb4n\x1b\x93\xc1o\x97\x88\xf8\x16\x05`v\x90\x84@\xc1\x17#A\xda\xdbxz\xa8\x9c\x89p\xca\x93dz;\x99-\xd7\x93y%Mc\xb0\x957d\xaf\x86\xa4*\xe9\x1dI\xea\x10\x02\x8e\xba\xf0\xd3*J\xf1\xe2y\xf65x(\"\xb5\xc0\x87\xecmj\x81]\x9e\xc9\xb4\xc0q\x81\xbe\x8d\xfe(\x9c\xcd\x8e\x08\x7f\xca\xd0\xe3\x1cr\xc7\xca]+\xf7\xac\"\x8a<\xeav\xe1\xd92-\xe1,p\x7fF3\xc5Ba\xe2K\x08\x93\x19,\x939\xfe.\x14\x1e\xc2\xcbk\xf43\x83I4\x0d\xd7Y\x84 \xdc\x9faT@\xb0\x8cR\x17\xe0gX\xac\xb3\x1cph\x00\x07?[\xb0L\xc9\n\xc2\xcf\x87\xb7(6?h\xff|x\xdb\xc1\x8f\xd1\x938\x03\xfb\x10\xd3\x86\xa6\xda\xd8\x8a\x12)\xbe\xca\x97xRP6q;\xb2-\\\x8a[\x9aDp\xd0\xc7\xef\xe5]\x1d\xc2w\xcb\x9b\xe8]\x94Z\xe8\xd1u\x98A\xb2\x84\xe9zBW-\x08\x0c\xc3s\xa4\xb2\x1a\xd1O0ML5\x01\".\xbbK\xf1~>\xa1\xa0\xa2\x8f\x85\xe1\xa5w)\xa7\x87\x9c.B\xa1\x8f\xf2lB\xdb\nR\xa6\xd2\xe9*\xdb\x95c#\xa4~:X\xaa_\x94F~\xe1Y\xeb\x84\x88\xcfF#\xe4\x9d)\xd0-0\xd3\nngH 8\xea\xc2o_\xc1\x08\xdc\xee?\xba\xbfA\xdb\xed\x98\xa2i\xbc\x84\xa5\x1d\xbe\xcbF\x10\x9cW4AR~\x0e\x8c\xc0\xeb\x9e\xbfv\xa1\xed\x99\x1bq\xe9:\x18\x80\x80\x00i\xe4q\xf7\xfc\xb5\x0fm\xc7\x8c\xc0k&\n\xfc\xca-\x89J\x8f\x88\x02QY#\n\x1fQ\xe9\xd55\xe1W\x9b\xf0a\x04\x83\xee?\x10\x1f\xba&\xe8\xba\xa2\x87\x9b(''\x02\x8d\xe7\x84JN\x14tL+\xb2\x89z\x0d\xd8X\xf8~\xc6\x82\xa6\xf3\xaf0M\x14\xa5\xaf\xa1\x8aw\xe9\x1b\xe2\xd2)\"\x86\xe2\xa0\xc0\xd1\xd3\xe0\x08\xd9\x10\x82\x10\xe4\x92h0\x0e\xd2\xc5\x07%9A\x1d9Da\\l\xd5\x85\x94\x91\xb6\x1cPu1\x88\x99S\x85@\xa1\n\x8e[G\x05a\x88t\x95[\xd1Y\x01\xc7\x01S\xdf\x81\xb1\xdb\xe9\x80I\x96\x8b\xbd\xa2\xdb\xff\x81\x84\xe3\x05\xdd\xf3\xd7\x1e\xc5\xe6\xf6\xbb\xe7\xaf\x03\xbd5H\x02\xe2T\xb1\x10\x10\xd5C\x9dA\x16\xbdu\xab\xe8--A\x07L\xbd\xa9\"\xd5\x07\xe8hx\xbf\x93\x0e>\xeag\x1eo\x0c{0\xefbM\x00x\x17\xbb\n\xb3@\xcf\x95\xe6B\x8c\xfc.v-\xb8\x8b\x0dA\xe0]\x8cz\xbe\x1e\x8e\x9b\xfa\x10x3,\x9b\xf5`XO\x1d_V\"j\xad\x88\xd5k\xf4W5k\xf4\xc6,\xce\xc6\x026\xe4 I\xc0/\xf8T\x0e\x05\xe0\xa6)U\x1d-\xef\x02\xdb+F\x95[qL\xd5VP;x\x9e[&w\xf5\x80%C\"q\xdf\xd6\xe6\"\xde \xb3@\xd2\xdb:\x12UJx\xa2\x8dP\xa9\x9d\x0dHL\xea\x91\x98\xd4\xbfoLz\xe7\xb8\x16\xac\x1d\x0b\xd6\xae\x05\x99cA\xe6ZpmAl\x01\xd2\xdek\xf4\x9fgA\xceE]\xba\xb4\x9c(\x0d6\x7fM\xb9=\xca\xa0\x88\xa5\x18\xd6\xc9g\x8a\xe5\xc4\x84\x95\x8e\xa2\xea\x9cM\xef\x0d\x1c\x9aL\xbcc-\xe2\xb7vc\xd5\xd6()K\x88\xad\xd5\xdb~\x88\xbd\xa3\x0e\xd9\x9bP\xcf\xe0\x94\x9e\xc1afP\x83<3!\xcf(\xf2[\x86\\\x0b\x94\xc9\xdc\x89\xad\xb2\xc1\xe4\xda\x82=\xa4F\x8e\x8c\x8a\x0c\x16\xb8X\xed\xdd\n\x141jM\x8f\x02\x17\xbb\xda\x89\xa8v\xaf\xfbu\xa7\xa2O\xcd*\xc6\x1d\x83\xbe\xc9SOr\x84M\n\xe3?@4\xcf\"\x19\x89Q\xa3\xc1\xac\xd56\x8f\x1eD\xcd\x86\x8a\xdej\xae.P)\xbcB\xb1\x91\xfd\xef\xa9G/\x02\x80\x9c\xc3\xde\xb5A\xcb\x90\xe7\xc0]\x7f-\xf4\x9bi\xd2tm K5\xb715\x9fS\x9d\xe4\x9ag\xc1pU\xdf\x850\xb8b\x10B\x80z\xed\xc9\xc5\xea\x18\xb8\x02&`\xd1\x0c\xf6\x8a\x0c\xc9\xc6\x82\x9e\x16\x15\x8e\xc1\xd4\xf6+\xe4X4=\xc9w\x94\x87\x0dP\xcb[\x01d:\x93B\x1b\xbb\xae_px3N\xa3l\x1a\xce\x9b\xe58\xf1\x10\x98\xf1\x03 \x9f\xa0\xf1\xc9`\xe8\xa0\xc1P7\xd0\xdd\xe9\x15\xf9\xee\xce\x82\xac>L\xa3\x1fwwB@\x0f\x94\x1e\xacZ\xdd\x11d\xaf\xdd\x06q<\xfd\xb8S\xbbU\x05hVm\x945{K\x9a\xf5j\x9a\xbd#\xb8\xee\x8c\xb8\xee0.\x9a\x871\x87\xe8di\xe5\x0e{\xa8<D\x9e\x10\xf5^;CcP\x0e\xf3(\xb1\x04x\xd2\xafR\x8fR\x1c[DG$\x9e/C!\xda\\\x0c#\xd4$\x1c(WI\xcf\xe1.\x13\xf66 \xd0S\xc9\x03\xd1\x1dHw\xe5n\x91$\x9c\xd3\xe4\xd7U\xfc.\xca`M6#\xfd\x85.*\xfd\xf6\x17\xbc\x17\x05=\xc2\xfc\x1f\n\xab\xd1\xe9\xab\xf8\xe2\x10\x07\xb9\xf8\xcbP*\xb9e%|\x8e\xe8\xa8\x0bgx\xd7\x13\x84\xf39\xdc\x92\x9d#\x19\x84i\x04q\x02h`\xa7q\x1ejx\x81[\xbf\x0c\xb3\x1c\xb0\x8d\xd2\x83>\x98\xe0L E\xb4\xe7\xca\xb2\x1c\xa6\x82\x1fXX\xb70\x12\xefd\xe2\x15\xf9l\xf4\xef.\x83\x11\xdc!\x08y\x9d\xff\xef\xcb\xf4wX\xaeS\xb8 oa\x12N\x7f\xbf \xd3Yf\xd1-\xe3H\x82w\x07\xd8\x9a3\xc8\x97\x80\xdd\x02~\xba9bB\x10\x85{s\x1d\xcf#h\xc7\x95N\x04\xda\xc11\x1aa\xa8B\xd4\x0f\xb2t\xd6\x96!\x8b\xc4\x7f\x10\x0f5Cm|p \x01\x08\xd6!N`\xb1\x90\xd1\xa8E>\xee2Etj\xbe0\x8e\xc5\xd4\xe5\x12K\xc5kj\x16\xa3\x1c\xf3\xe2\xce\x86\x8b*\xf4P\xb7\x8d\xa0\xee(\x14\xe6\xe3\xcbYt\x19'\x11\x9c=\xfd\xe1\xd7\xe7/\xc7/\x9f|\xf3\xfcl\xfc\xd7\xb3\x97\xe3\xbf\x9e\xb5Sk\x95FVb\xddt`\xb6\x84\x7f\xc1? fa\xd2\xd8n'\x1d\xd8C\xdd7\x1a\xe1\xa0P \x94t\xe0t\x04\x07\xed6~\x83H\xbb}\xd39p:\x1d\xdc\xed\x86*'#\x00s\x15|B<\xe9P\x05cO\xd1\xbfn;\xed\xc0\x08\xda\xab4\xea\xbcB0\x07N\xe7\xc8\xbd(j\xb2\xa8\x8f\xaf#\xa8\x06^io\xa7\x1d\x0b\xf6(\x92\x83\x02K\x87C\xf3\xcf\xc7\x8f>\x10Mo\xdb\x1d\xb2\x0eb\x90\xe9\xf8\x97\x97?\xbdx\xa2\x96m\xabU+Y\x19\xa4V\xae\x8a\nf\xa9\xb6ZU\x99\xb6Z-A4\xe2\x9a\xb8 #ID\xad\x16/\xe7-\xf0\xc8\xb2\x96\xab\x96\xbd\xd3N;e[\xe8C\xee\x0ds.\xe0Nq\x82\xf6\xfe\xd9\x00\xf5\xd9b\xd4\x06\x1f\x14\x1d\x7f\x9a\xac@xg\xdd'3\xa0\x9b\xc3\xd7\xcf\xb9[%\x92\xfa\xf4\x02\xa2\x10s\xeeZ\xe4\xd3\xe31\x0b\xbeoRY7\x92Q\xd1\x10P\xc0\xd7\xd1\xc1\x92q\x82\xb4\x89&\xd0[T\xa2\xc1#\x9d\xd0\x93\x9a\xf5Un\xcbi:iU[E\xb9`\xdfj\xe9E^\x15\x96&\xcdA\x88 \xcbIW\xc1\xaej8\xe0s\"\xff/gDv\xf9\x10iXS\xe5C\xec\xfal\xc8\x9f>c\x81'EX\xc1\xeet\xb3\xecrf\xb5\xcbG\xfc\xa7\xe4#\xaa\xfb\x97\xa2\xb7\xe3\x8d\xe1~\x0f\xc5\x1e0yS\x93X#\xb5 U\xad.Q]L\x8b\xbc\xaaRVHP\xdcN\xa3\xd4m\xe8A\xd3R\xb7jv\x86\xe2&\\Y.\xfa\xa5\xb8wa\xaaX\x88k*\x8d;\xd7\x82;\x8fm\xa5m\xb2\xbb\xc3\xbc\xfd\x979\x03\x00\xd5\xee\xdc\"\xf4\xe2\xf6@\xa8=6\x1d\xb0\x8cYn:=\xf4\xca\xb4\xe3\x9di\xa5.\x14W\xf5j@\xf9E=\xf5\xc6\x81rh\x0f\xd9\xd0\x0e\x82\xfb\xe0\x96\xd1\xc4\x0d\x7fz\x85\x8f\xa6\x8b\xf5<\x1f\xdf$\xe1\xe5y\x1b\x15u\xd1W\xb2_\x0e\xa7nd]Gs\xf20-\xdf8u\xa3\xe8g\x06\x93\xb1^D\xc8\xc2,\xc7\x1cL\xe2\x1cF\xe5M\xb8\xa8\x8c<\xb2\xb9'Y|\x95p\xc3\x00\xbe\x1c\x1e\x1fP\xe0\xa3\x93E\xb4\xc8\xa2\xfc\xbcM(\xb6-<\xcf\xef\xe2L\xd0\xf2\x12?}e_p\x87Y2>\xfa\x14\xc7;B1\xb9<?\xce34\xc4[\xe0\xf6zH\xc8\x9a\xe8\x93V)\xdcP\x86\xbc\x94\x10\x96\x11\x1e\nN\x8b\x8d:4i\x81\xb8>A4\x8b\xe3p\x92C\xb2\xbc\x19\x8aOn\x96\xe9\x8c\x7fTO\xfc$\xce-:\xb3+_\x05\x10'y\x07\xcb\xb12\x82O\xe2|\x7f\x7f(>\x9b.\x93<N\xd6\x918\x16\x97?\x92\xe5\x0d\x8c\xe0F\xa2\x0b==\xa5)\x97I\x9cWZ\"\xb5\x8ar\x1dr\xc41\x8c\xaa\xf2f\\R\xb3f\x9c&\xcb\x9b\x0e\xec\x13%\x11\x92NLm\xda\x18\xe1\xe9)\xb4o\xf0|tO\x881p\xe1\xc1\x88B\x9f\x9c`\xae\xb8b\xa4K\x938\xbf@\x14\xa1n\xed\xca=\"\xa97a\xac,FO\xf7G\\\xc7~\xc0;\xbbA\xa1\x10n/\x10dF\xa6\xd5\xf5\xbd\xbd\xbf\xcf\xfa\xbb\xbcn\x02O\xeb\xc8w:\n\x08t\xee\xd7\x9d\x80\xa5\xdea9\x9b\x8d\xd9Y\x9c\x8c\xe4x\x89\xb3H\xaa~\x7f\x95Fo*\xe9\xdd;\xfdLW\xe1>p\xc9\xac\xe2\x01\xd1H\x13\x8e\xaf\"\x0bf\xe3\xab\x88\xf3\x0c\xb1b\n\"\xc7\xa1{\xb32\x10%\xb0\x08 \xce\xcb\xce\x8a\xa4,~t\x8b\x1f\xdd\xf2\x8fj\xe6F\xd5,\x1f!3\xb4`ovX\x0c%H2\xafl\x9a\x0b\xc6\x8dK\x05\xb7\xac\xe0V*(\xe2N\xf1\xb1\x92\xac;\xf6r\xd2\"[[\xdc\x84\xee\x0c!\x86\x13H\xaa\xb7_\x89r\xe370\xec\xe1\xc6p\xb2\x92|;p\xd0\xf7\x19fP\xcc\x8f\x16\xe6{\xd4\xa5\x98\xbbp\x16N\xafi\xea<N\xe0+\x84\xe2+\xbc\xf13\x84;\x98.\x97\xe9,N\xc2<\x82|\xb9\x84l\x11\xce\xe70\xb9\x85\x10.\xc3i\xbeLay _\xcd\x0e\xef\xbe:\x84\x9f\x92\xf9m\x81TJ\xca\x7f\x95\x89\xb8b\xee\xee\x8bu\x16\xcd \xbf^\xae\xaf\xae-\xc8\x96\xf0f\x9d\xe5\xb0^\xcdp\x9b\xd7a.\xef6U\x0c\xcd\x98\xed\xe4\xc0\xb98\xbccB(~\xd1\xde\xbd\x97\x05\x15\xeb&\xe4z\x94\xb0\xb2\xbbi\x95F[\xaf\x93\xe8\xac \x93-$\x0b\x7f\xf9\xfe\xb7\xb3\xf6\xdf\xbf\xff\xf1\xdb\x9f\xfe>~\xd2\xb9P\xc4\x1b\xe7H\x97j\xea\xb0\x0e\x87\xa7\xcb\xc5j\x9d\x93d\xfdr6+\x8e\xeee\xa8\xdf\xff\xbfp\xba\x9c\xc4a\x82W+\x0e\x15\xc26\xf9\x19\x03\x05\x16\x10os\x97r\xd7y\x1du\xe1\x9b\x94\xae&, _\x92\x13\xee\xe1\"\x82\xdf`\x16%\xcb\x05\xd2\x92e\xaa\"C\xbf\x98UG\x84\x05E\xcf0\x92:u\xbb\xd6 \xd3\xe7\xedf\x87\x93\xa6\xf9\xa6\xeal\xb7I \x16\x81[b,\xbcR\xaa\x10\xd6\xa0qX\xa7\x0e\xd5j\xf9b\xa5:\x14v\x0e\xbfq\x0e\x1c\x0d\xaf\xe3$|\xe5\xf6\x8a\xcbMiX\x98\x8d\x8b\xeb\x11K\xc0+5\xe0\x954$\xf0\xa5C\xd2\x11T?&\xebx>\xc3\xc8\xe4\x0b\xf2\x90\xafL\xc2R7( \xd8G\x8cta3%\xdf\xc2Pn/\xb0\x80\xfd\x80B:\xc3\x12\x1f \x0f(g\xa5\x01\x15\x17\xe6\x89\xe6\xb3\xbc\x84\xb0\xf0R\xf0d>\xe7\xca\xc24\x82I\x8a\x9c[.)\xfaW\x9c\xa6\x7fe\xa1\x00cz\x8d\x1c#\xd2\xa7hV\xa0\x8b\x13\xf8\xed\x10\xbe]Gx\xb5\x8dq\xf7\x15\xc4\xd9r\xb1LW\xd7q\xb6\x80\x9b\x08\xa6a\x02\xb3%^\x8b\\\x16\xab\xedH#\xf2(\x99\xc5\xc9\x15\xe7\x99\xe9\x8d\x12\xbf\xf1\x0e\xf9&\xc4w5\xac\xb3\x08\xc2K\xbclQ\xdc\x17\x88\x1c\xc2z\x1e\xa2\xc12\x99\xc1t\x99\xa6\xd14\x17\x1c\xbd\x80\x89\xae\xc8\xd2\x9b\xa7\x96\xc94bWXD\xc9\xac\x94\xd2K\xf4\x00_\x12@\x8f\xe3\xe3S\xc5i4%Nj\x06\x7f%\x0b\xb5t\x8d\x94\xc9\x07\x89\x93\x8d\x1c\x05.B\xf1!vpa\x8aF\x13\"\xe8I\x98EdxA:\xb3\xcc\xaf\xa3\xb4@\x97_G\xb7\xf4\xa04\xfc\x06X^\x05\xbe\xe5%8G\xbf\xe1\xc1\x88J\x16\xc9\xa5:\x00\xb3U\x03F\xdc:\xa3W`\xa0\x1e.;\x90\xeb\xa8| \xd1\xe5e<\x8d\xa3$\x9f\xdf\"\x19\x93\xeb\x1cC\xf8=Y\xde$\xf0\x1b\xc4\xc9\xbb(\xcd\"\xfd\xa0\xb7\xcdh\x85\x1d\x82\x05{\xbf \x97\x1bRSlb0W\xbc\xc1\\\x89\x06\xf3W>\x9f\xc9p\x9eb\xecB\xe0\"\xd8\xd3\x95\x1c\x88\x88R\x15WM\x8b\x0dZEx\x84q\x1d\x90(I\xf3\xbe\x18\x14\xf2rA\xbf>\xdcL-H\x85h\x13\x8a\xf5\xe8\x93\xc2\xa9\xec\xedA\x1b\xcd\x10\x99\xfb\x8b/\xaa\x99U\xd5\xa2\xe9\x1er\xaa\x16\xd0\x0eH\xac\x8a\x97Q\xd3\xc7\x87u\x84>\x8aH\xcc\xce\xea\xe8\xbd\x92\xe8\xbdjJo\xb1 I\x9b\xc3#YI\xf5_\xeb\xa9.W\xd0\x04\xba\xf7~S\x10.\x1c\xcb\xf9Bw2H\x11\xe7\x89\xf9\xdb\xdf\xb8\xa8\xd6\x18\xde\xcd\xb2p\x8c\xa6\x84a\xbeN\xa3\xf1|\x19\n/6\xa3\xe3j\x17\x84\x0cY\xf14\xb3\xf4\xb8Pq\\\x8e\xc6x\xcaO2\x1b\x15Dx\xd6\xe7\xb9\x02\x87\xab4~\x17\xe6\xd1x\x11-\xa6\xab[|{\\\x16_\x1d\x9c\xce\xc2<\xc4\xa7\x82=a\xd9I\x02\xcf\x04p\xcf\x15\xe0?\xc0\xe3G_\xc6\x97`?~\xd4\x92S\xf92md\xae\xe9\xb9\xe7\n\n\xd0\x14\xb2\xdb\x11\xb4O_]A\x91T\xff\xc3\xe3G_\xa2\xf1\xe8r\xab\x1e\xcb\xc2w\xc2\xce3e/h\x03&\xdc\xb1\xda\xb2\xecS\xf5\x9e$\xb8\xb4\xa6\xf7dAeb\xef\xd5\xf6Y\xf1\x0eI\xb9]cW\xa9j\x91\xe6e[\x92S\x90b\x8f\xac\xc24\x8b\xc6h\xac\x0e\xa7y\x83\xae\x91\xe2g\xe9\xbd\x97\xf8\x1d\x9a\x81o\xc8R\"\xd3\xe4\xc2\xc54\xca\xa5\xcc\xe3\xf2]\x94^\xceq\xdaJ5\xfd\x975\x15'\xd4i\xb3Xl{\x0c\x01\x93\x03jbo\x04_\xb0\xe7\x95\x00\xb9\x822\xe3Pb\x996\xc5\x89\xf7\xd9F\xb9\xc6\xf9i\x8c\x01I\x15s\x91\xe9\x95\x86%_1\xb0m\xb1\xack\x17\xf9,\xae\xbf\xa1L=\xa5QnLE\xaf\xd6\x93\xdf\xa3\xdb\x8a\x0b\xbdB\x1d}\x15U\xcd\x8c\xc0\x9fw\x81|1\xdb\x1a7\x97\xc2\xf6\xc6i\x04\xd0\xadi\xd7QB\x02,U%\xc8oW8\xb5\x10m\xc2)\n\xaf\x02\x1f&\xb7yD\xc2\xda8\xcfJ\\\xd0\x95g\x15q\x92\xc5\xb3\xa8J\xba\x05a\x86\xd8BQ\x19\x8dT\xdfE\xe9-\xde\xcbw( \xfcqI\x13\x16Uy\xa1>#'m\x11%\xc5\x1c@$\xe1P\xb3\x0f\x90\xe7039\x14\x0b\xf6H{\x9c;\x08|\xb5?P\\\x19\x81\xb3E\xbc\x1f\xd0\x8d\x1fG]\xf8 \xc5\xd27q\x16Yp\x893B\xe1\xf4w\x14\xdc*^\x9a\x8bb\xb7s<u\xf8\x87\x8eC\xe98\x92\\\xc8\xd9\xd8\xc6\x02\x9eE5oB\x8d[\xb1\x06\xecKnY\x943\xbdj\x02\x8bb\xc3\xce\x12\x818p\x01TO\xbd\x7f t\xb3\xd7/gO\xff\xe6\xf6\x82\xffu\xc6gO\xc7O\x7f\xfa\xe1o/\xce~\xf9\xe5\xec[\x00\xb2\xd5\xca\xeeh\xd7x\x90\x9ePu\xc1\xde\xb5\x92k\x8a\xe6\xd1\xc2R;\xd0\xd5zb\xb1\xdd\xb5\xe8\xa3bgx\xf8\xf2pt\xb8ZOp\xf6\x11\xdf\xbe\xe4\xc2\xfb\xf7 <\xf1tk)\xb8\x938\xc1\xa9\x96,\x99\xd8\x8b\x9e\xdaw:\xa8\xd1\xaa\x90\xe9F\x05\xc2\x13\x05\xe6\x89\x10}\x1a\xcfF\xd0\xab\xb2\xe1W\xd8\x08*O\xfaF\xc6D\xed\x8b\xab\x975\xa88{\xff\x1e\xb4PD\xef\xf6=\xaf\x1a\x7fK\xf7:\x80\x18\xd1+\x15\xb2\x94\xd3\x9e\xb0\xfb\x17\xef\xd2\xabe\\\xec\x02\xfe&\x08r\x0dD\xdb$\xa8z\x8a+\x9aP\xb9^\n\x91\xaf\x1f\xa6\xaa\xf7\\\x98\xd6B9;\xc9\xa24\xa6' \x95\xb6b\xb0\x92n\x867\xda\xf1\xabnp9\x0f\xaf\xa4pPb\xa9\x9c\x9ab\x8e\x14K\xdd[\xdd\xd6\x81\x90\xe8\x8e\xe2\xaba\xd5\xe7%\xcb\xa8\x0eu$N\xfeK\xa8\x113\x98=\xd8\xd3\xb9(\x81\x99.\xb16\xf0\xf8\xedzLK\xa8\xe3\xd0\xdd.\xc2(\x85\xff\x83\x00\x1d\xf8\x1a}\xd8\xfa\xeegm\x05=M[\xbe\xce\xcb\x8b|{^\xc9\xf8\xad:\xbcqL\xc7l\xb9\xb1\x9a\xd7')\x84\x91\x0eJ\xa0\xb0\xe7\xa3\xa2\x9a\xfaq^\x80\x10\x0e\xbcf\x16j\xdd\x10\x12T\xc2\x01T\xa5\x0c \xaa}!\x9e\x04\xd6\xab\xffU\xd4\xd1\x8e\xbd\xb2\xe6^E\x9c\"6\x82\xbe\xd5B\x17=\xcesfAM\x1b\xcaZ8\x12\xa0Uo\x9be\x12\xae\x14\xaf\xbf!{k\x8a.mp\x81\x10E\x81wg)\xcd\x99\x03(\xcf2\xcbnP\x1b+T\xf4U?\xe5*\xbc!\xfe\xc5\xefr\x10\xf9\xfb\xb9\xb2\x9d\x83\xe1\xe6&\x154\xc2\xe7=\xce\x17\x1a\xbfMi\xde\xfb\xd9\x02JGA\xc0V.U\xb0XF\xd2\xde\xcf\x1d\xf1\x10E\xd9k\xa4\x08\x14\xf1\x1b\x9a9\xcc\xa2K\xc8\xf2t=\xcd\x19\x0d\xa2\xcc\xb0\x11\x05\xf8mo\x1f\x84\xae@\xf3\xb34\x9a\xa2Y\x1dN\xc3\x96\xb3\xdf\xa1a\x1c\xa3\xb3:Vs\xab5&\xed\xd2P\x16_\x19\x93\x1d\xf1UV9\xe9%\xea\x89\x02\xe9\"\xca\xb2\x10\x85\xc4d\xea=\x8d\xcbK\xa3D M\xd2\x0d\x9a\xf9*t\xfa\x1c.7\xd5\xab\x19\xaf\xb8\x90\x92\x7f\xfa\xe6\x1c6o\xaa\xe0E2 a\x9b\xddU(\xdf\x9c\xc3[\\\x99\xf3\xc9\x12\n\xe4\xcb\xee\xa2t\x89g\xc6)\x8e\xe3\x8c \x99Y-\xf1\xb665\xb1\xa5\xeb\x99\xa4\x1bd+WE~Fp\xb5\x82\xfdsQ\xe4\xe5\xc6BR\xed\x90\x1bZ&\xe9\x06\xa6\xcbE\x94\x91;VC \x8d\xe0\x85\x8a8\x83y\x94eh\x02J\xa6\xc8\xcbt\x16\xa5C\x98Fi\x1e\xc6\xc9\xfc\x96+^\x15\xf30\x92z\x98\xc63\xd8\x031\xbbU\xd9k\\\xbc\xf4\x1d\x13\xb5'\xab2\xd6\x9e\xf1j\xbc\x88\x93u6\xc6\x8d\x9f\xe3c)\xd53_M\xe3_\xba1\xd4\xdc\"ni\x1cfH\xc9\xa4A_rA\xd2\xd4\x03\x07\xd3\x081\xe3\xdfi\xd0\xcb +[qw\xc2\xde\xe6\x8d\xfa\x96\n\xa6Od]\x87\xed\xe7LDe\xa8\x80\xd3]\xf4\x8e\x05\x18\x96\x9a\xa0\x16\xbc\xd8\xe1\x86k\xa8v\xe6\x8bx]\x8a\x17+w\x05\x96\xadzc_\xb3\xf7\x163\xf6\x06\xef\x82\xd7 \x97v\x9e\x16\xae\xf8\xed\x1b\xc9\xe1~!\nO\x88)(tm^X\xe9j59b\xb5[\xfe\xa8|\xb1\xca\x0d\xeeR\xc7\xc0\x8d\xcfEq\x80\xefa\xc6\xa2\xaa\xd9\xe0\xaa\xef\xd7\x9aL\xb3\xb1\x83\x1be\x9dU\xfd\xa9\x18s\xfe\xdb\x13\xd0F\xab+\x93\xd1\xd4\x9d\xea\xb5\xf1\xd3\xe7\xa4\xcbP\x8a\xdd\xaf\xfd\xe0\x91\x14.\xce,| \x91\xfeS\x9e\x05l\x1aZu\xe0\xf1#eD5U\xc6S\xaczq\xe2/Q\x86\\\x9bT\x1d[\x11\xaa\xdeh\n\xd3\xe1g\x0c\x9d\x8a\xd3\x845\xe3e\xa6\x1d\xab\xaa\xe3e\xd6`\xbc\xe4\x86\xc1L;\x14\x0b\xc3;\x15\x1a\xcb&\xd7\x0d\x9a\xab\xb4\xc8\xc6+FN9\xb7$\x8f\x84\xab\xb4NlJ\xae\n\x17=\xd5\xb1$e2\x91\x86\xebi*\x0f\xd9`H\x1dU\xdc\xde\xf9\x96!j\xc4(d\xab\xad\x89\x1a[\xad:\xce\xcb\x18\xd1\x80_\x15#~\nv\xa5\xae\xb9g\xe4\xb2\xfd~\x848\xc9\xbb\xc4\xcfV]K\xed\xb0x\xef\xa0E\xbd\xfeF*T\x96\xde<\xf7#\x96\xde\xa4%\xcf\x8f[\x82S\xad\x9fn\xb9\x16\xf7\xc0\xfb4ZG\xdd\xda\x98\xed\xb3n\xd1\x00n\xe3Y\x97L\x8fFbX\xd7\xe8 Z\xb17\x97\x9e\xac7^6\xd3x\x8f\xec}/\x95\x89\x9b\\*\xc3o\x91\xa6#\x10\xdb\xd08\x0f\xb3\\\xd8\xc4N\xf6C\x12\xfd\xc6\xafS\xe6\xeab`\xba\x91r\xb9\xceW\xeb\\\xbf\xf6I^\xbb\xbdw\x17\xd3;G\xca\xd3\x08\xa0\x9bd\xa9/*\xc1\xa74E{%W\xb9\xe4\x9f\xe5*\x17\x81'z\x0c/\xc6t\xe9ni\xf9\xa8kYb\x1e\x9bt-\x8b.Y\xca-\x18I\x93\x01\xd2I\xe5\xf2\x10\xf9\xad<]WI\xb0\x1a\x16\x91D=/\xf3\xa8t\xd4\xa8\xa4m\xe9`\xb0\xf7s\x11g\xc0\xde\x9eND\xba\xb50T\x9b\xf1\xc3\xf1A(\xeb\xe8\x12\xca\xdc\xb0\xb1U\x04\xbd\xd5\x08\x84\x03g\xea\xd5\xcb\xe8\xd9<O[dW\x9ekU;\x80\x85\xd7\x1aa\xbf\xd5\x86\xcd\xdc\\\xaeZ\xc8^\x8aWL\n\x15\x93\xb9\xfa\xd1\x9cM\x86\xf6\xe8(]\x94\x97\xe1\x07\xcd\xbb\x9d\x80\x8d\x82h\xf2\xe3\x14<\x1a\xf7H\x89v{SN\x95\xb8D{5>*\xe6[\xfcM)\x95\x99\xe2\xc2\x02*U\xce\xf9\xb7\xa4\xe8M\x91\xa2&\xb1-\xe3\xed\xad\x05\x08\x13\x99\xf0Q\xba[\x15\x8d\x96\xb2\xf3oIS<\xa1\x8d\x99\xe5\xb9m\xb5P\xbc\x89\xfe\x93s\xf9*\xc5\xdeff\xd8\x05\xe5\xccP\xde\xd9\x86U\xd9\x02~\x0e\xd8H\x8f5\xee\x84\xd3f\x90\x96/>Z\x97\xb7\xd6\x04\xb5\xc2\xeb\x94\x1c\x05\x95\xa8\x16\x12|\xbeX\xc1H\xef\xd7\xde\xf2~M\xd5@\xd1S\nU#Z@\xbb;_\xacX\x87\xe3\xb3l]\xf8\xdf(M\xa29\xa0\xefG\x95\x15\x9d\x1f\x10\x93\x86u\x1d2\xcd\xfe\x80\xc1\x86\x8a\x15\xa1\xb3\xfc\xfao\x98p\xac\xb2\xfa\x85\xa1\x02\x0e#\x19\x8f\x7f'DI\x01\xd2r:\xbf\x8f\xc7\xa5\x9a\xa9\x055{\xde4\x8b\xaf\xf0r\xa9Ae\x89\x98\x90\xaa\x92\x85\xd5\xa2\xb8\xe4\x9f\xea\xe9x\xb9\xce;8k\xd1jH@\x16_\x89\x0bsL\xf3WL`\x92\\\xc9\x90F\xc1\xa8\x80[t\x80.\xc65\xb6q\xa0U8\xec\"\x03\x87\x1f\xc5\xb3\x0d\x8c\x00\xcd\x8c '\xe3x\xd6\xb6\xa9\"\x11`&\x97W\xf1lsq\xc8E\xb8\xad\xa6\xbc\xc9I\xca=\xec\x19\xaax\xb9\xe4\x98\x0e1S|\x8c\x81v\x03\x8f`\xafL?HH\x94\x9bb8\x01Z\xb0\xc7\x05\x03{\xec!\x91\x05\x99\xaa\x8c\xf3%\x95R\xbb\xecd\xbeu a1{\xe4\x9e\x96\x01\xc6\xd1\x11\xaf\x9a\x9b\\p\xc5\x80?\xe2(\x830\x81(\x99.g\xa8\xd7\x89\x00\xcb\xd1\xf2\x10a\xc1\x98^`\xab\xcf\xbe\x06\xe7\xeb\xb2\x18\xcf\x04\xc3y<C \xadV\xcb\x96\xca\xe2\xa4(\x85'\xe9U\xf6uk\x9ao\xben\xb5\xf0\x19\xa0(E1o\x88\x14?\x8f69,'o\xa2i\x0e\xedi\x98$K\xfcJ\x94\x1f\x7f}\xfe\xbc\x83Q\x7f\x9f|\x0d-\xda\x9d_\x8b\xd5\x03\x9f\xecx,\x1bVbh\xb5hgJ\xd5\xd9\x86I\x9a\xb0\xd2U&\xb2\xc5\xf5\x81\xab\xbfZO\xe6\xf1\x14\x90Y\x92\x0e\nzx\xda\x9d\xa1\xa9\xd0U~\xad@W\xef\x92\xee1V\xd6x$i\xd0dN\xa8\xa9\xef!\xc5\x9c\x07\x8a\xf2k\xa6\x82\x05\x10\xb2\xf5n\x1ae4\x95Z\xb1\xaf\xed\x1cQ\x99\xe3\xb7\xab~i\xb5\x9eH\xde\x88T\xe4\xbdQ\x9d\xf7)l\x0eG=V\xc1\x91`mE\x08\xd4\xe90\x9c\xf2\xae\x8a\x99i[>\xf1\"\x157\xd4)sk\x8c\xc1\x0f\xc56\xcb/T>\x85m\xd8`R\xc7;\xe9\n\xa6U\xf8\xb8\xf0\x8e<\xd6Ed\x8d\xdd]\x8b$\x8b[i\x94a\x08\xbc\xb2DW\x06\xfeo\x00\x00\x00\xff\xffPK\x07\x08\xe6\xe6\xa6\x81\x08D\x00\x00(\xd9\x01\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x06F\x19Q\xe6\xe6\xa6\x81\x08D\x00\x00(\xd9\x01\x00\x04\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x81\x00\x00\x00\x00k.clUT\x05\x00\x01L\xd0D_PK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00;\x00\x00\x00CD\x00\x00\x00\x00"
fs.Register(data)
}
// +build opencl
package opencl
/*
#cgo CFLAGS: -I.
#cgo LDFLAGS: -L . -loclsp -lOpenCL
#include "oclsp.h"
*/
import "C"
import (
"github.com/CaduceusMetaverseProtocol/MetaCryptor/xecc/types"
"sync"
"time"
)
const (
defaultMaxBuff = 100000
defaultMaxIdle = time.Millisecond * 300
defaultMaxWait = time.Second * 2
)
type basetask struct {
rwmux sync.RWMutex
busy bool
lastm time.Time
firstm time.Time
tasks []*types.TaskWithReport
}
func (b basetask) add(task *types.TaskWithReport) {
b.rwmux.Lock()
defer b.rwmux.Unlock()
if len(b.tasks) == 0 {
b.firstm = time.Now()
}
b.tasks = append(b.tasks, task)
b.lastm = time.Now()
}
func (b basetask) len() int {
b.rwmux.RLock()
defer b.rwmux.RUnlock()
return len(b.tasks)
}
func (b basetask) ready() bool {
b.rwmux.RLock()
defer b.rwmux.RUnlock()
return len(b.tasks) >= defaultMaxBuff || // buffer is full
(len(b.tasks) > 0 && time.Now().After(b.firstm.Add(defaultMaxWait))) || // first item wait timeout
(len(b.tasks) > 0 && time.Now().After(b.lastm.Add(defaultMaxIdle))) // task idle timeout
}
func newBaseTask() *basetask {
return &basetask{
tasks: make([]*types.TaskWithReport, 0),
}
}
package xecc
import (
. "github.com/CaduceusMetaverseProtocol/MetaCryptor/xecc/types"
)
type Session struct {
xecc *Xecc
result chan XTask
closeCh chan struct{}
}
func (s *Session) AddTask(task XTask) error {
ts := MakeTaskWithReport(task, s.result)
return s.xecc.addTask(ts)
}
func (s *Session) GetResult() chan XTask {
return s.result
}
func (s *Session) closed() bool {
select {
case _, ok := <-s.closeCh:
if !ok {
return true
}
default:
return false
}
return false
}
// Close called by user.
func (s *Session) Close() {
if !s.closed() {
close(s.closeCh)
}
}
package types
func SafeWriteXTask(ch chan XTask, task XTask) error {
var err error
defer func() {
if r := recover(); r != nil {
// use closed channel
err = ErrChanClosed
}
}()
select {
case ch <- task:
err = nil
default:
err = ErrChanIsFull
}
return err
}
func SafeWriteXTaskWithReport(ch chan *TaskWithReport, task *TaskWithReport) error {
var err error
defer func() {
if r := recover(); r != nil {
// use closed channel
err = ErrChanClosed
}
}()
select {
case ch <- task:
err = nil
default:
err = ErrChanIsFull
}
return err
}
package types
import (
"errors"
)
var (
ErrChanIsFull = errors.New("channel is full")
ErrChanClosed = errors.New("channel is closed")
ErrRequestTimeout = errors.New("request timeout")
)
type FeatureId byte
const (
FeatureBase FeatureId = iota
FeatureSecp256k1RecoveryPubkey
FeatureSecp256k1RecoverableSign
FeatureSecp256k1Sign
FeatureSecp256k1Verify
FeatureEcdsaP256Sign
FeatureEcdsaP256Verify
FeatureSM2Sign
FeatureSM2Verify
)
type XTask interface {
TaskName() string
TaskId() FeatureId
}
type XTaskSecp256k1RPubkey struct {
Msg []byte
Rsig []byte
Pubkey []byte
Address []byte
}
func (x *XTaskSecp256k1RPubkey) TaskName() string {
return "Secp256K1-Recover-Pubkey"
}
func (x *XTaskSecp256k1RPubkey) TaskId() FeatureId {
return FeatureSecp256k1RecoveryPubkey
}
type XTaskSecp256k1RSign struct {
Msg []byte
Privk []byte
Rsig []byte
}
func (x *XTaskSecp256k1RSign) TaskName() string {
return "Secp256K1-Recoverable-Sign"
}
func (x *XTaskSecp256k1RSign) TaskId() FeatureId {
return FeatureSecp256k1RecoverableSign
}
type XTaskSecp256k1Sign struct {
Msg []byte
Privk []byte
Sig []byte
}
func (x *XTaskSecp256k1Sign) TaskName() string {
return "Secp256K1-Sign"
}
func (x *XTaskSecp256k1Sign) TaskId() FeatureId {
return FeatureSecp256k1Sign
}
type XTaskSecp256k1Verify struct {
Msg []byte
Sig []byte
Pubkey []byte
Verify bool
}
func (x *XTaskSecp256k1Verify) TaskName() string {
return "Secp256K1-Verify"
}
func (x *XTaskSecp256k1Verify) TaskId() FeatureId {
return FeatureSecp256k1Verify
}
type XTaskEcdsa256Sign struct {
Msg []byte
Privk []byte
Sig []byte
}
func (x *XTaskEcdsa256Sign) TaskName() string {
return "EcdsaP256-Sign"
}
func (x *XTaskEcdsa256Sign) TaskId() FeatureId {
return FeatureEcdsaP256Sign
}
type XTaskEcdsa256Verify struct {
Msg []byte
Sig []byte
Pubkey []byte
Verify bool
}
func (x *XTaskEcdsa256Verify) TaskName() string {
return "EcdsaP256-Verify"
}
func (x *XTaskEcdsa256Verify) TaskId() FeatureId {
return FeatureEcdsaP256Verify
}
type XTaskSM2P256Sign struct {
Msg []byte
Privk []byte
Sig []byte
}
func (x *XTaskSM2P256Sign) TaskName() string {
return "SM2P256-Sign"
}
func (x *XTaskSM2P256Sign) TaskId() FeatureId {
return FeatureSM2Sign
}
type XTaskSM2P256Verify struct {
Msg []byte
Sig []byte
Pubkey []byte
Verify bool
}
func (x *XTaskSM2P256Verify) TaskName() string {
return "SM2P256-Verify"
}
func (x *XTaskSM2P256Verify) TaskId() FeatureId {
return FeatureSM2Verify
}
type TaskWithReport struct {
XTask
ch chan XTask
}
func (t *TaskWithReport) Report() error {
return SafeWriteXTask(t.ch, t.XTask)
}
func MakeTaskWithReport(task XTask, report chan XTask) *TaskWithReport {
return &TaskWithReport{
task,
report,
}
}
type Engine interface {
Name() string
Ready() bool
Support(XTask) bool
Process(XTask) (XTask, error)
ProcessA(*TaskWithReport) error
ProcessBatch([]XTask) ([]XTask, error)
}
package xecc
import (
"github.com/CaduceusMetaverseProtocol/MetaCryptor/xecc/engine/cpu"
"github.com/CaduceusMetaverseProtocol/MetaCryptor/xecc/types"
"sync"
)
var (
xeccHandle = &Xecc{}
)
type Xecc struct {
cpue types.Engine
wg sync.WaitGroup
mux sync.Mutex
close chan struct{}
initOnce sync.Once
}
func XeccInstance() *Xecc {
xeccHandle.mux.Lock()
defer xeccHandle.mux.Unlock()
xeccHandle.initOnce.Do(func() {
xeccHandle.cpue = cpu.GetInstance()
xeccHandle.close = make(chan struct{})
})
return xeccHandle
}
func (x *Xecc) Secp256k1RecoverPubkey(msg []byte, sig []byte) ([]byte, error) {
return cpu.GetInstance().Secp256k1RecoverPubkey(msg, sig)
}
func (x *Xecc) Secp256k1RecoverableSign(msg []byte, key []byte) ([]byte, error) {
return cpu.GetInstance().Secp256k1RecoverableSign(msg, key)
}
func (x *Xecc) Secp256k1Sign(msg []byte, key []byte) ([]byte, error) {
return cpu.GetInstance().Secp256k1Sign(msg, key)
}
func (x *Xecc) Secp256k1Verify(msg []byte, sign []byte, pubkey []byte) (bool, error) {
return cpu.GetInstance().Secp256k1Verify(msg, sign, pubkey)
}
func (x *Xecc) EcdsaSign(msg []byte, key []byte) ([]byte, error) {
return cpu.GetInstance().EcdsaSign(msg, key)
}
func (x *Xecc) EcdsaVerify(msg []byte, sign []byte, pubkey []byte) (bool, error) {
return cpu.GetInstance().EcdsaVerify(msg, sign, pubkey)
}
func (x *Xecc) SM2Sign(msg []byte, key []byte) ([]byte, error) {
return cpu.GetInstance().SM2Sign(msg, key)
}
func (x *Xecc) SM2Verify(msg []byte, sign []byte, pubkey []byte) (bool, error) {
return cpu.GetInstance().SM2Verify(msg, sign, pubkey)
}
func (x *Xecc) Process(task types.XTask) (types.XTask, error) {
return x.cpue.Process(task)
}
func (x *Xecc) AsyncSession() *Session {
s := &Session{
xecc: x,
result: make(chan types.XTask, 100000),
closeCh: make(chan struct{}),
}
return s
}
func (x *Xecc) addTask(tws *types.TaskWithReport) error {
return x.cpue.ProcessA(tws)
}
.idea
.vscode
protocol
gen
MIT License
Copyright (c) 2022 CaduceusMetaverseProtocol
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# Protobuf generated go files
PROTO_GO_FILES = $(shell find . -path -prune -o -type f -name '*.pb.go' -print | grep -v vendor)
#PROTO_GO_FILES = $(patsubst %.proto, %.pb.go, $(PROTO_FILES))
DEST=${PWD}
BIN=protocol
.PHONY: all build generate deps clean lint
all: build generate lint
build: $(PROTO_GO_FILES)
@buf build
lint: generate main.go
@go build -o $(BIN)
generate:
@buf generate
deps:
@go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
@go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2
@go install github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway
@go install github.com/bufbuild/buf/cmd/buf@v1.9.0
clean:
@rm -f $(PROTO_GO_FILES) $(BIN)
@rm -rf gen
# Uber Protobuf Style Guide V2
* [V1 versus V2 Style Guides](#v1-versus-v2-style-guides)
* [Spacing](#spacing)
* [Package Naming](#package-naming)
* [Package Versioning](#package-versioning)
* [Directory Structure](#directory-structure)
* [File Structure](#file-structure)
* [Syntax](#syntax)
* [File Options](#file-options)
* [Imports](#imports)
* [Reserved Keyword](#reserved-keyword)
* [Enums](#enums)
* [Enum Value Names](#enum-value-names)
* [Nested Enums](#nested-enums)
* [Messages](#messages)
* [Message Fields](#message-fields)
* [Oneofs](#oneofs)
* [Nested Messages](#nested-messages)
* [Services/RPCs](#servicesrpcs)
* [Streaming RPCs](#streaming-rpcs)
* [HTTP Annotations](#http-annotations)
* [Naming](#naming)
* [Documentation](#documentation)
This is the V2 of the Uber Protobuf Style Guide.
See the [uber](uber) directory for an example of all concepts explained in this Style Guide.
## V1 versus V2 Style Guides
The V2 Style Guide contains 39 new lint rules compared to our [V1 Style Guide](../etc/style/uber1/uber1.proto)
that represent lessons we have learned in our API development. The rules within this Style Guide
will help you write clean, consistent, and maintainable APIs. We recommend following the V2 Style
Guide instead of the V1 Style Guide - once you understand the rules described below, and are used
to developing with them, it becomes simple to follow.
However, for backwards-compatibility reasons, the V1 Style Guide is the default style guide
enforced by Prototool if no lint group configuration is present. To use the V2 Style Guide with
Prototool, set the following in your `prototool.yaml`.
```yaml
lint:
group: uber2
```
The V2 Style Guide is almost entirely a superset of the V1 Style Guide. There are only two items
that are incompatible.
- Nested enum value names do not need to have their message type as part of their prefix.
- The `go_package` file option is now suffixed by the package version and not `pb`.
We call out these differences below. Even if you are primarily using the V1 Style Guide, we still
recommend you follow the remainder of the rules in the V2 Style Guide, although they will not
be enforced by Prototool unless the `uber2` lint group is set.
**[⬆ Back to top](#uber-protobuf-style-guide-v2)**
## Spacing
Use two spaces instead of tabs. There are many schools of thought here, this is the one we chose.
**[⬆ Back to top](#uber-protobuf-style-guide-v2)**
## Package Naming
Some conventions:
- A **package name** is a full package name, i.e. `uber.trip.v1`.
- A **package sub-name** is a part of a package name, ie `uber`, `trip`, or `v1`.
- A **package version** is the last package sub-name that specifies the version,
i.e. `v1`, `v1beta1`, or `v2`.
Package sub-names should be short and descriptive, and can use abbreviations if necessary.
Package sub-names should only include characters in the range `[a-z0-9]`, i.e always lowercase
and with only letter and digit characters. If names get too long or have underscores, the
generated stubs in certain languages are less than idiomatic.
As illustrative examples, the following are not acceptable package names.
```proto
// Examples of bad package names.
// Note that specifying multiple packages is not valid Protobuf, however
// we do this here for brevity.
// The package sub-name credit_card_analysis is not short, and contains underscores.
package uber.finance.credit_card_analysis.v1;
// The package sub-name creditcardanalysisprocessing is longer than desired.
package uber.finance.creditcardanalysisprocessing.v1;
```
The following are acceptable package names.
```proto
// Each package sub-name is short and to the point.
package uber.trip.v1;
// Grouping by finance and then payment is acceptable.
package uber.finance.payment.v1;
// Ccap is for credit card analysis processing.
package uber.finance.ccap.v1;
```
Package sub-names cannot be any of the following.
- `internal` - This is effectively a reserved keyword in Golang and results in the generated
package not being accessible outside of its context.
- `public` - This is a reserved keyword in many languages.
- `private` - This is a reserved keyword in many languages.
- `protected` - This is a reserved keyword in many languages.
- `std` - While not a reserved keyword in C++, this results in generated C++ stubs that do not
compile.
**[⬆ Back to top](#uber-protobuf-style-guide-v2)**
## Package Versioning
The last package sub-name should be a major version of the package, or the major version
followed by the beta version, specified as `vMAJOR` or `vMAJORbetaBETA`, where `MAJOR` and `BETA`
are both greater than 0. The following are examples of acceptable package names.
```proto
package uber.trip.v1beta1;
package uber.trip.v1beta2;
package uber.trip.v1;
package uber.trip.v2beta1;
package uber.trip.v2;
package something.v2;
```
As illustrative examples, the following are not acceptable package names.
```proto
// No version.
package uber.trip;
// Major version is not greater than 0.
package uber.trip.v0;
// Beta version is not greater than 0.
package uber.trip.v1beta0;
```
Packages with only a major version are considered **stable** packages, and packages with a major
and beta version are considered **beta** packages.
Breaking changes should never be made in stable packages, and stable packages should never depend
on beta packages. Both wire-incompatible and source-code-incompatible changes are considered
breaking changes. The following are the list of changes currently understood to be breaking.
- Deleting or renaming a package.
- Deleting or renaming an enum, enum value, message, message field, service, or service method.
- Changing the type of a message field.
- Changing the tag of a message field.
- Changing the label of a message field, i.e. optional, repeated, required.
- Moving a message field currently in a oneof out of the oneof.
- Moving a message field currently not in a oneof into the oneof.
- Changing the function signature of a method.
- Changing the stream value of a method request or response.
Beta packages should be used with extreme caution, and are not recommended.
Instead of making a breaking change, rely on deprecation of types.
```proto
// Note that all enums, messages, services, and service methods require
// sentence comments, and each service must be in a separate file, as
// outlined below, however we omit this here for brevity.
enum Foo {
option deprecated = true;
FOO_INVALID = 0;
FOO_ONE = 1;
}
enum Bar {
BAR_INVALID = 0;
BAR_ONE = 1 [deprecated = true];
BAR_TWO = 2;
}
message Baz {
option deprecated = true;
int64 one = 1;
}
message Bat {
int64 one = 1 [deprecated = true];
int64 two = 2;
}
service BamAPI {
option deprecated = true;
rpc Hello(HelloRequest) returns (HelloResponse) {}
}
service BanAPI {
rpc SayGoodbye(SayGoodbyeRequest) returns (SayGoodbyeResponse) {
option deprecated = true;
}
}
```
If you really want to make a breaking change, or just want to clean up a package, make a new
version of the package by incrementing the major version and copy your definitions as
necessary. For example, copy `foo.bar.v1` to `foo.bar.v2`, and do any cleanups required.
This is not a breaking change as `foo.bar.v2` is a new package. Of course, you are responsible
for the migration of your callers.
Prototool is able to detect breaking changes in your Protobuf definitions. See
[breaking.md](../docs/breaking.md) for more details.
**[⬆ Back to top](#uber-protobuf-style-guide-v2)**
## Directory Structure
Files should be stored in a directory structure that matches their package sub-names. All files
in a given directory should be in the same package.
The following is an example of this in practice.
```
.
└── uber
├── finance
│ ├── ccap
│ │ └── v1
│ │ └── ccap.proto // package uber.finance.ccap.v1
│ └── payment
│ ├── v1
│ │ └── payment.proto // package uber.finance.payment.v1
│ └── v1beta1
│ └── payment.proto // package uber.finance.payment.v1beta1
└── trip
├── v1
│ ├── trip_api.proto // package uber.trip.v1
│ └── trip.proto // package uber.trip.v1
└── v2
├── trip_api.proto // package uber.trip.v2
└── trip.proto // package uber.trip.v2
```
**[⬆ Back to top](#uber-protobuf-style-guide-v2)**
## File Structure
Files should be named `lower_snake_case.proto`.
All files should be ordered in the following manner.
1. License Header (if applicable)
2. Syntax
3. Package
4. File options (alphabetized)
5. Imports (alphabetized)
6. Everything Else
Protobuf definitions should go into one of two types of files: **Service files** or
**Supporting files**.
A service file contains exactly one service, and its corresponding request and response messages.
This file is named after the service, substituting `PascalCase` for `lower_snake_case`. The service
should be the first element in the file, with requests and responses sorted to match the order
of the declared service methods.
A supporting file contains everything else, i.e. enums, and messages that are not request or
response messages. These files have no enforced naming structure or otherwise, however the general
recommendation is that if you have less than 15 definitions, they should all go in a file named
after the last non-version package sub-name. For example, for a package `uber.trip.v1` with less
than 15 non-service-related definitions, you would have a single supporting file
`uber/trip/v1/trip.proto`. While there are arguments for and against the single file
recommendation, this provides the easiest mechanism to normalize file structure across a repository
of Protobuf files while making it simple for users to grok a Protobuf package without having to
change between multiple files, each requiring many imports.
The following is an example of a supporting file with two definitions. Note that it is merely
coincidence that the file is named `trip.proto` and it contains a definition `Trip` - there is
no need to name files by a type or types contained within them, other than for services.
```proto
syntax = "proto3";
package uber.trip.v1;
option csharp_namespace = "Uber.Trip.V1";
option go_package = "tripv1";
option java_multiple_files = true;
option java_outer_classname = "TripProto";
option java_package = "com.uber.trip.v1";
option objc_class_prefix = "UTX";
option php_namespace = "Uber\\Trip\\V1";
import "uber/user/v1/user.proto";
import "google/protobuf/timestamp.proto";
// A trip taken by a rider.
message Trip {
string id = 1;
user.v1.User user = 2;
google.protobuf.Timestamp start_time = 3;
google.protobuf.Timestamp end_time = 4;
repeated Waypoint waypoints = 5;
}
// A given waypoint.
message Waypoint {
// In the real world, addresses would be normalized into
// a PostalAddress message or such, but for brevity we simplify
// this to a freeform string.
string postal_address = 1;
// The nickname of this waypoint, if any.
string nickname = 2;
}
```
The following is an example of a service file named `uber/trip/v1/trip_api.proto` showing a service
`TripAPI` with two service methods, and requests and responses ordered by method. Note that
request and response messages do not require comments.
```proto
syntax = "proto3";
package uber.trip.v1;
option csharp_namespace = "Uber.Trip.V1";
option go_package = "tripv1";
option java_multiple_files = true;
option java_outer_classname = "TripApiProto";
option java_package = "com.uber.trip.v1";
option objc_class_prefix = "UTX";
option php_namespace = "Uber\\Trip\\V1";
import "uber/trip/v1/trip.proto";
import "google/protobuf/timestamp.proto";
// Handles interaction with trips.
service TripAPI {
// Get the trip specified by the ID.
rpc GetTrip(GetTripRequest) returns (GetTripResponse);
// List the trips for the given user before a given time.
//
// If the start index is beyond the end of the available number
// of trips, an empty list of trips will be returned.
// If the start index plus the size is beyond the available number
// of trips, only the number of available trips will be returned.
rpc ListUserTrips(ListUserTripsRequest) returns (ListUserTripsResponse);
}
message GetTripRequest {
string id = 1;
}
message GetTripResponse {
Trip trip = 1;
}
message ListUserTripsRequest {
string user_id = 1;
google.protobuf.Timestamp before_time = 2;
// The start index for pagination.
uint64 start = 3;
// The maximum number of trips to return.
uint64 max_size = 4;
}
message ListUserTripsResponse {
repeated Trip trips = 1;
// True if more trips are available.
bool next = 2;
}
```
**[⬆ Back to top](#uber-protobuf-style-guide-v2)**
## Syntax
The syntax for Protobuf files should always be `proto3`. It is acceptable to import `proto2` files
for legacy purposes, but new definitions should conform to the newer `proto3` standard.
**[⬆ Back to top](#uber-protobuf-style-guide-v2)**
## File Options
File options should be alphabetized. All files should specify a given set of file options that
largely conform to the [Google Cloud APIs File Structure](https://cloud.google.com/apis/design/file_structure).
Note that `prototool create` and `prototool format --fix` automate this for you, and this can be done
as part of your generation pipeline, so there is no need to conform to this manually.
The following are the required file options for a given package `uber.trip.v1` for a file named
`trip_api.proto`.
```proto
syntax = "proto3";
package uber.trip.v1;
// The csharp_namespace should be the package name with each package sub-name capitalized.
option csharp_namespace = "Uber.Trip.V1";
// The go_package should be the last non-version package sub-name concatenated with the
// package version.
//
// Of special note: For the V1 Style Guide, this was the last package sub-name concatenated
// with "pb", so for a package "uber.trip", it would be "trippb", but since the V2 Style Guide
// requires package versions, we have changed "pb" to be the package version.
option go_package = "tripv1";
// The java_multiple_files option should always be true.
option java_multiple_files = true;
// The java_outer_classname should be the PascalCased file name, removing the "." for the
// extension.
option java_outer_classname = "TripApiProto";
// The java_package should be "com." plus the package name.
option java_package = "com.uber.trip.v1";
// The objc_class_prefix should be the uppercase first letter of each package sub-name,
// not including the package-version, with the following rules:
// - If the resulting abbreviation is 2 characters, add "X".
// - If the resulting abbreviation is 1 character, add "XX".
// - If the resulting abbreviation is "GBP", change it to "GPX". "GBP" is reserved
// by Google for the Protocol Buffers implementation.
option objc_class_prefix = "UTX";
// The php_namespace is the same as the csharp_namespace, with "\\" substituted for ".".
option php_namespace = "Uber\\Trip\\V1";
```
While it is unlikely that a given organization will use all of these file options for their
generated stubs, this provides a universal mechanism for specifying these options that matches
the Google Cloud APIs File Structure, and all of these file options are built in.
**[⬆ Back to top](#uber-protobuf-style-guide-v2)**
## Imports
Imports should be alphabetized.
Imports should all start from the same base directory for a given repository, usually the root of
the repository. For local imports, this should match the package name, so if you have a file
`uber/trip/v1/trip.proto` with package `uber.trip.v1`, you should import it as
`uber/trip/v1/trip.proto`. For external imports, this should generally also be the root of the
repository. For example, if importing [googleapis](https://github.com/googleapis/googleapis)
definitions, you would import `google/logging/v2/logging.proto`, not `logging/v2/logging.proto`,
`v2/logging.proto`, and such.
Imports should never be `public` or `weak`.
Note that the
[Well-Known Types](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf)
should be used whenever possible, and imported starting with `google/protobuf`, for example
`google/protobuf/timestamp.proto`. Prototool provides all of these out of the box for you.
```
.
└── google
└── protobuf
├── any.proto
├── api.proto
├── compiler
│ └── plugin.proto
├── descriptor.proto
├── duration.proto
├── empty.proto
├── field_mask.proto
├── source_context.proto
├── struct.proto
├── timestamp.proto
├── type.proto
└── wrappers.proto
```
These are available for browsing at
[github.com/protocolbuffers/protobuf/src/google/protobuf](https://github.com/protocolbuffers/protobuf/tree/master/src/google/protobuf)
and are also included in the `include` directory of each [Protobuf Releases ZIP
file](https://github.com/protocolbuffers/protobuf/releases).
**[⬆ Back to top](#uber-protobuf-style-guide-v2)**
## Reserved Keyword
Do not use the `reserved` keyword in messages or enums. Instead, rely on the `deprecated` option.
The following is an example of what not to do.
```proto
// A user.
message User {
// Do not do this.
reserved 2, 4;
reserved "first_name", "middle_names"
string id = 1;
string last_name = 3;
repeated string first_names = 4;
}
// The type of the trip.
enum TripType {
// Do not do this.
reserved 2;
reserved "TRIP_TYPE_POOL";
TRIP_TYPE_INVALID = 0;
TRIP_TYPE_UBERX = 1;
TRIP_TYPE_UBER_POOL = 3;
}
```
Instead, do the following.
```proto
// A user.
message User {
string id = 1;
string last_name = 3;
repeated string first_names = 5;
string first_name = 2 [deprecated = true];
repeated string middle_names = 4 [deprecated = true];
}
// The type of the trip.
enum TripType {
TRIP_TYPE_INVALID = 0;
TRIP_TYPE_UBERX = 1;
TRIP_TYPE_UBER_POOL = 3;
TRIP_TYPE_POOL = 2 [deprecated = true];
}
```
By far the most important reason to use `deprecated` instead of `reserved` is that while not a wire
breaking change, deleting a field or enum value is a source code breaking change. This will result
in code that does not compile, which we take a strong stance against, including in Prototool's
breaking change detector. Your API as a whole should not need semantic versioning - one of the core
promises of Protobuf is forwards and backwards compatibility, and this should extend to your
code as well. This is especially true if your Protobuf definitions are used across multiple
repositories, and even if you have a single monorepo for your entire organization, any external
customers who use your Protobuf definitions should not be broken either.
As of proto3, JSON is also a first-class citizen with respect to Protobuf, and JSON serialization
of Protobuf types uses field names, not tags. This means that if you have JSON consumers, re-using
the same field name is a breaking change. Therefore, when removing a field, if you ever use JSON
or ever could use JSON, you must reserve both the tag and the field name, as done in the above
bad example. If you have to reserve these, it is easier and cleaner to just deprecate the field.
**[⬆ Back to top](#uber-protobuf-style-guide-v2)**
## Enums
Enums should always be `PascalCase`. Enum values should be `UPPER_SNAKE_CASE`. The enum option
`allow_aliases` should never be used.
All enums require a comment that contains at least one complete sentence. See the
[Documentation](#documentation) section for more details.
There are many cases when it's tempting to use a string or integer to represent a value that has a
small, finite, and relatively static number of values. These values should almost always be
represented as enums and not strings or integers. An enum value carries semantic meaning and there
is no ability for incorrect values to be set.
**[⬆ Back to top](#uber-protobuf-style-guide-v2)**
### Enum Value Names
Enum values have strict naming requirements.
1. All enum values must have the name of the enum prefixed to all values as `UPPER_SNAKE_CASE`.
For example, for an enum `TripType`, all values must be prefixed with `TRIP_TYPE_`.
```proto
// The type of the trip.
enum TripType {
TRIP_TYPE_INVALID = 0;
TRIP_TYPE_UBERX = 1;
TRIP_TYPE_POOL = 2;
}
```
This is due to Protobuf enums using C++ scoping rules. This results in it not being
possible to have two enums with the same value. For example, the following is not valid
Protobuf, regardless of file structure.
```proto
syntax = "proto3";
package uber.trip.v1;
enum Foo {
CAR = 0;
}
enum Bar {
// Invalid! There is already a CAR enum value in uber.trip.v1.Foo.
CAR = 0;
}
```
Compiling this file will result in the following errors from `protoc`.
```
uber/trip/v1/trip.proto:10:3:"CAR" is already defined in "uber.trip.v1".
uber/trip/v1/trip.proto:10:3:Note that enum values use C++ scoping rules, meaning that enum values
are siblings of their type, not children of it. Therefore, "CAR" must be unique within
"uber.trip.v1", not just within "Bar".
```
2. All enum values must have a 0 `INVALID` value.
For example, for an enum `TripType`, there must be `TRIP_TYPE_INVALID = 0;`.
3. The invalid value carries no semantic meaning, and if a value can be purposefully
unset, i.e. you think a value should be purposefully null over the wire, then
there should be a `UNSET` value as the 1 value.
For example, for an enum `TripType`, you may add a value `TRIP_TYPE_UNSET = 1;`.
Protobuf (proto3 to be specific) does not expose the concept of set vs. unset integral fields (of
which enums are), as a result it is possible to create a empty version of a message and
accidentally create the impression that an enum value was set by the caller. This can lead to hard
to find bugs where the default zero value is being set without the caller knowingly doing so. You
may be thinking - but it is super useful to just be able to assume my default enum option, just
like I want an integer field called count to default to 0 without setting it explicitly. However,
Enum values are not integers, they are just represented as them in the Protobuf description. Take
for example the following enum:
```proto
// This is not a valid example.
enum Shape {
SHAPE_CIRCLE = 0;
SHAPE_RECTANGLE = 1;
}
```
In this case a consumer of this Protobuf message might forget to set any `Shape` fields that exist,
and as a result the default value of `SHAPE_CIRCLE` will be assumed. This is dangerous and creates
hard to track down bugs.
Following similar logic to our INVALID case, we don't want information in messages to be implied,
we want signal to be stated with intention. If you have a case where you want `UNSET` to be a
semantic concept, then this value must be explicitly set. For example:
```proto
// The traffic light color.
enum TrafficLightColor {
TRAFFIC_LIGHT_COLOR_INVALID = 0;
TRAFFIC_LIGHT_COLOR_UNSET = 1;
TRAFFIC_LIGHT_COLOR_GREEN = 2;
TRAFFIC_LIGHT_COLOR_YELLOW = 3;
TRAFFIC_LIGHT_COLOR_RED = 4;
}
```
It's tempting to use `UNSET` as a default value, but then again we risk the case of a user
forgetting to set the value and it being interpreted as the intentional value `UNSET`. For
consistency across our enums, if `UNSET` is a semantic value of your enum, it should have the
value 1.
**[⬆ Back to top](#uber-protobuf-style-guide-v2)**
### Nested Enums
Nested enums are allowed, but **strongly discouraged.**
While allowed, **a good general policy is to always use unnested enums.**
Nested enums should not be referenced outside of their encapsulating message.
The following is valid but discouraged.
```proto
// A traffic light.
//
// Discouraged.
message TrafficLight {
// A traffic light color.
enum Color {
COLOR_INVALID = 0;
COLOR_UNSET = 1;
COLOR_GREEN = 2;
COLOR_YELLOW = 3;
COLOR_RED = 4;
}
string id = 1;
Color current_color = 2;
}
```
Note that the enum value prefix follows the same convention whether nested or unnested.
Of special note: For the V1 Style Guide, enums had their nesting types prefixed as well,
so in the above example you would have had `TRAFFIC_LIGHT_COLOR_INVALID`. This was dropped
for the V2 Style Guide.
While the above example is valid, you should not reference a `TrafficLight.Color` outside of the
`TrafficLight` message as a matter of convention - if referencd outside of `TrafficLight`, the enum
has meaning in other contexts, which means it should be top-level. If you need to reference an enum
outside of a message, instead do the following.
```proto
// A traffic light color.
enum TrafficLightColor {
TRAFFIC_LIGHT_COLOR_INVALID = 0;
TRAFFIC_LIGHT_COLOR_UNSET = 1;
TRAFFIC_LIGHT_COLOR_GREEN = 2;
TRAFFIC_LIGHT_COLOR_YELLOW = 3;
TRAFFIC_LIGHT_COLOR_RED = 4;
}
// A traffic light.
message TrafficLight {
string id = 1;
TrafficLightColor current_color = 2;
}
```
Only use nested enums when you are sure that for the lifetime of your API, the enum value will not
be used outside of the message. In the above example, there could easily be situations where we
want to reference `TrafficLightColor` in other messages in the future.
```proto
// Statistics on a traffic light color.
message TrafficLightColorStats {
string traffic_light_id = 1;
TrafficLightColor traffic_light_color = 2;
google.protobuf.Timestamp last_active_time = 3;
google.protobuf.Duration total_duration = 4;
}
```
In most cases, you cannot be sure that you will never want to use an enum in another message,
and there is no cost to having an enum be unnested.
**[⬆ Back to top](#uber-protobuf-style-guide-v2)**
## Messages
Messages should always be `PascalCase`.
All messages require a comment that contains at least one complete sentence, with the exception of
request and response messages as described in the [Services](#services) section. See the
[Documentation](#documentation) section for more details.
Messages should be used to represent logical entities that have semantic meaning. They should not
be used to group common fields that carry no meaning themselves.
The following is an example of what not to do.
```proto
// Do not do this.
message CommonFields {
string id = 1;
google.protobuf.Timestamp updated_time = 2;
}
// Do not do this.
message Vehicle {
CommonFields common_fields = 1;
string vin = 2;
}
// Do not do this.
message User {
CommonFields common_fields = 1;
string name = 2;
}
```
This is commonly done to simplify server-side implementations of Protobuf APIs. There are sometimes
operations you want to do on request types that require a common set of fields, so it seems to make
sense to group them as messages in your Protobuf schema.
You should optimize your Protobuf schema for the simplicity and semantic value of the API, not for
for your server-side implementations. `CommonFields` has no semantic meaning - it's a
pair of a couple fields that are part of messages that do have semantic meaning. A user of your
API does not care that these fields are common, they only care what a `Vehicle` is, and what
a `User` is. Thinking of this as JSON, the following has no meaning.
```json
{
"common_fields": {
"id": "asdvasd",
"updated_time": "timestamp",
},
"vin": "asdvasdv"
}
```
The key `common_fields` has no meaning, `id` and `updated_time` are fields of a vehicle. Therefore,
the following is what you would want as a consumer of the API:
```json
{
"id": "asdvasd",
"updated_time": "timestamp",
"vin": "asdvasdv"
}
```
In our example, you would copy the fields between `Vehicle` and `User`.
```proto
// A vehicle.
message Vehicle {
string id = 1;
google.protobuf.Timestamp updated_time = 2;
string vin = 3;
}
// A user.
message User {
string id = 1;
google.protobuf.Timestamp updated_time = 2;
string name = 3;
}
```
Messages that will always contain a single field are strongly discouraged. Sometimes, it is
tempting to use messages to confer type information.
```proto
// Do not do this.
message VehicleID {
string value = 1;
}
```
The above is generally done because Protobuf happens to generate specific struct or class types in
each language, and therefore have semantic meaning. However, this is not how Protobuf values are
intended to be typed, and this can explode in a myriad of ways. To be consistent in our User
example, we would need to do the following.
```proto
// Do not do this.
message UserID {
string value = 1;
}
// Do not do this.
message Name {
string value = 1;
}
// Do not do this.
message User {
UserID id = 1;
Name first_name = 2;
Name last_name = 3;
repeated Name middle_names = 4;
}
```
When taken further, this becomes nightmarish to work with both in terms of internal
implementations, and from an API standpoint. The code in most languages will require
so many Builders or struct initializations just to set single values that it becomes
extremely tedious to iterate on an API. While less important, the JSON structure
also explodes.
```json
{
"id": {
"value": "sdfvsavassava"
},
"first_name": {
"value": "John"
},
"last_name": {
"value": "Smith"
},
"middle_names": [
{
"value": "Foo"
},
{
"value": "Bar"
}
]
}
```
As compared to:
```json
{
"id": "sdfvsavassava",
"first_name": "John",
"last_name": "Smith",
"middle_names": [
"Foo",
"Bar"
]
}
```
If a message will always be a single value, prefer that single value for fields. You will thank us
later.
**[⬆ Back to top](#uber-protobuf-style-guide-v2)**
### Message Fields
Message field names should always be `lower_snake_case`.
While there is no enforcement of this, we recommend that message field names match their type in
lieu of a name that makes more sense. The following is an example of this pattern.
```proto
// A vehicle
message VehicleState {
string vehicle_id = 1;
// The field name matches the type PositionEstimate.
PositionEstimate position_estimate = 2;
// The field name is the plural of the type VehicleFeature.
repeated VehicleFeature vehicle_features = 3;
// The map is from key type to value type.
map<string, Order> order_id_to_order = 4;
// Timestamps are the exception, see below.
google.protobuf.Timestamp time = 5;
}
```
The built-in message field option `json_name` should never be used.
The following additional naming rules apply.
- Field names cannot contain `descriptor`. This causes a collision in Java-generated code.
- Field names cannot contain `file_name`, instead using `filename`. This is just for consistency.
- Field names cannot contain `file_path`, instead using `filepath`. This is just for consistency.
- Fields of type `google.protobuf.Timestamp` should be named `time` or end in `_time`. For example,
`foo_time`.
- Fields of type `google.protobuf.Duration` should be named `duration` or end in `_duration`. For
example, `foo_duration`.
**[⬆ Back to top](#uber-protobuf-style-guide-v2)**
### Oneofs
Oneof names should always be `lower_snake_case`.
**[⬆ Back to top](#uber-protobuf-style-guide-v2)**
### Nested Messages
Nested messages are allowed, but **strongly discouraged.**
While allowed, **a good general policy is to always use unnested messages.**
Nested messages should not be referenced outside of their encapsulating message.
The following is valid but discouraged.
```proto
// A Vehicle.
//
// Discouraged.
message Vehicle {
// A vehicle type.
message Type {
// Should probably be an enum.
string make = 1;
string model = 2;
uint32 year = 3;
}
string id = 1;
Type type = 2;
}
```
While the above example is valid, you should not reference a `Vehicle.Type` outside of the
`Vehicle` message as a matter of convention - if referencd outside of `Vehicle`, the message has
meaning in other contexts, which means it should be top-level. If you need to reference a message
outside of a message, instead do the following.
```proto
// A vehicle type.
message VehicleType {
// Should probably be an enum.
string make = 1;
string model = 2;
uint32 year = 3;
}
// A vehicle.
message Vehicle {
string id = 1;
VehicleType vehicle_type = 2;
}
```
Only use nested messages when you are sure that for the lifetime of your API, the message value
will not be used outside of the message. In the above example, there could easily be situations
where we want to reference `VehicleType` in other messages in the future.
```proto
// Statistics on a vehicle type.
message VehicleTypeStats {
VehicleType vehicle_type = 1;
uint64 number_made = 2;
}
```
In most cases, you cannot be sure that you will never want to use a message in another message,
and there is no cost to having a message be unnested.
**[⬆ Back to top](#uber-protobuf-style-guide-v2)**
## Services/RPCs
Services should always be `PascalCase`. RPCs should always be `PascalCase.`
Services should always be suffixed with `API`. For example, `TripAPI` or `UserAPI`. This is for
consistency.
All services and RPCs require a comment that contains at least one complete sentence. See the
[Documentation](#documentation) section for more details.
Please read the above [File Structure](#file-structure) section carefully. Each service should
be in its own file named after the service. For example, `TripAPI` should be in a file named
`trip_api.proto`.
Every RPC request and response should be unique to the RPC, and named after the RPC. As per the
[File Structure](#file-structure) section, the request and response messages should be in the
same file as the service, underneath the service definition and in order of the RPCs defined
in the service.
The unique request/response requirement is for compatibility as you iterate your RPC definitions.
If one were to use the same request or response message for different RPCs, and then need to add or
want to deprecate a field, each RPC that uses this request and response message would be affected,
regardless of whether or not the new field applied to each RPC, or whether the deprecated field
was deprecated for each RPC. While this pattern can cause some duplication, it's become the "gold
standard" for Protobuf APIs.
The following is an example of such a pattern.
```proto
// Handles interaction with trips.
service TripAPI {
// Get the trip specified by the ID.
rpc GetTrip(GetTripRequest) returns (GetTripResponse);
// List the trips for the given user before a given time.
//
// If the start index is beyond the end of the available number
// of trips, an empty list of trips will be returned.
// If the start index plus the size is beyond the available number
// of trips, only the number of available trips will be returned.
rpc ListUserTrips(ListUserTripsRequest) returns (ListUserTripsResponse);
}
message GetTripRequest {
string id = 1;
}
message GetTripResponse {
Trip trip = 1;
}
message ListUserTripsRequest {
string user_id = 1;
google.protobuf.Timestamp before_time = 2;
// The start index for pagination.
uint64 start = 3;
// The maximum number of trips to return.
uint64 max_size = 4;
}
message ListUserTripsResponse {
repeated Trip trips = 1;
// True if more trips are available.
bool next = 2;
}
```
Note that request and response types do not need documentation comments, as opposed to all other
messages.
**[⬆ Back to top](#uber-protobuf-style-guide-v2)**
### Streaming RPCs
Streaming RPCs are allowed, but **strongly discouraged**.
If you'd like to enforce this, add the following to your `prototool.yaml`.
```yaml
lint:
group: uber2
rules:
add:
- RPCS_NO_STREAMING
```
Streaming RPCs seem enticing at first, but they push RPC framework concerns to the application
level, which results in inconsistent implementations and behavior, which results in lower
reliability. It is rare that a problem solved by streaming cannot be solved in a unary manner.
Spencer Nelson wrote a great summary of the issues with streaming RPCs in
[this GitHub Issue comment](https://github.com/twitchtv/twirp/issues/70#issuecomment-470367807),
which we paraphrase here:
Unary calls, while limiting, prevent many problems being created if you only give unary RPC
capabilities to an inexperienced developer as part of your tool kit. While you can make mistakes in
API design and message design, those mistakes stay local, they largely aren't architectural or
infrastructural.
Streams are different. They imply expectations about how connection state is managed. Load
balancing them is really hard, which means that a decision to use streams for an API has
ramifications that ripple out to the infrastructure of a system.
How plausible is it that users trip on that pothole? Unfortunately, it is quite likely. Streaming
is the sort of feature whose downsides can be hard to see at first. "Lower latency and the ability
to push data to the client? Sign me up!" But people could easily reach for it too early in order
to future-proof their APIs, "just in case we need streams later," and walk themselves into an
architectural hole which is very difficult to get out of.
Most simple streaming RPCs can be implemented in terms of request-response RPCs, so long as they
don't have extreme demands on latency or number of open connections (although HTTP/2 request
multiplexing mostly resolves those issues anyway). Pagination and polling are the obvious tools
here, but even algorithms like rsync are surprisingly straightforward to implement in a
request/response fashion, and probably more efficient than you think if you're using HTTP/2,
since the transport is streaming anyway.
Sometimes you really do need streams for your system, like if you are replicating a data stream.
Nothing else is really going to work, there. But Protobuf APIs do not need to be all things for all
use-cases. There is room for specialized solutions, but streams are a special thing, and they have
resounding architectural impact.
**[⬆ Back to top](#uber-protobuf-style-guide-v2)**
### HTTP Annotations
[HTTP annotations](https://github.com/googleapis/googleapis/blob/master/google/api/annotations.proto)
for use with libraries such as [grpc-gateway](https://github.com/grpc-ecosystem/grpc-gateway)
are allowed, but **strongly discouraged**.
If you'd like to enforce this, add the following to your `prototool.yaml`.
```yaml
lint:
group: uber2
rules:
add:
- RPC_OPTIONS_NO_GOOGLE_API_HTTP
```
HTTP annotations provide an alternative call path for RPCs that is not structured per the main
Protobuf schema. One of the benefits of Protobuf is having this structure, and generated clients
which properly call each endpoint.
**[⬆ Back to top](#uber-protobuf-style-guide-v2)**
## Naming
Some names are disallowed from all Protobuf types. The following names are not allowed to be part
of any package, option, message, message field, enum, enum value, service, or RPC, with any
capitalization.
- `common` - Common has no semantic meaning. See the above discussions on not having common
messages. Use a name that reflects the actual meaning of what you are representing instead.
- `data` - The name "data" is a superfluous decorator. All Protobuf types are data. Use of
"data" also causes singular vs plural issues during iteration, as the singluar of "data" is
"datum". If you must have a type that needs such a decorator, use "info" instead.
- `uuid` - We use "id" instead of "uuid" for purposes of consistency. An ID is meant to be
a UUID unless otherwise specified.
**[⬆ Back to top](#uber-protobuf-style-guide-v2)**
## Documentation
All comments should use `//` and not `/* */`. This is for consistency.
Comments should never be inline, instead always being above the type.
```proto
// A foo. Note that "A Foo." is a complete sentence as we define it.
message Vehicle {
// Comment here.
string id = 1; // Do not do inline comments.
}
```
While not enforced, aim for a 120 character maximum length for comments.
You must document your messages, enums, services, and RPCs. These types require at least
one complete sentence, represented as starting with a capital letter and ending with a period.
The following are some general recommendations.
**Message Documentation**
Description of message. Consider including:
- Assumptions and requirements (e.g. "This polygon must have its points in a counter-clockwise order.").
**Message Field Documentation**
Description of field. Not required, but recommended. Consider including:
- Assumptions and requirements.
- What happens when the field is left blank. Does it default to a specific value or throw an invalid argument error?
**Service Documentation**
Explanation of what the service is intended to do/not do. Consider including:
- Advantage or use cases.
- Related services (mark with the `@see` annotation).
**RPC Documentation**
Explanation of what the RPC is intended to do/not do. Consider including:
- Advantages or use cases (e.g."Useful when you want to send large volumes and don't care about latency.").
- Side effects (e.g."If a feature with this ID already exists, this method will overwrite it.").
- Performance considerations (e.g."Sending your data in chunks of X size is more efficient.").
- Pre-requisites (e.g. "You must complete registration using the X method before calling this one.").
- Post-requisites (e.g. "Clean up the registered resource after use to free up resources.").
**[⬆ Back to top](#uber-protobuf-style-guide-v2)**
# MetaProtocol
Define base protocol-buffer.
Please read [Guide](ProtobufStyle.md) first when you modify the *.proto* files.
# Add new module proto
1. install cloudstd
```go
go install github.com/slavovojacek/cloudstd@latest
```
2. add new module
```go
cloudstd proto --package "cmp.xxx.v1" --resource "shelf,shelves"
```
## Modules
/\
/ \
/ \
ring/gateway contract
/ \
/ \
/ \
<--------------
validator
#!/bin/bash
modulename=${1:-""}
cloudstd proto --package "meta.$modulename.v1" --resource "shelf,shelves"
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto2";
package gogoproto;
import "google/protobuf/descriptor.proto";
option java_package = "com.google.protobuf";
option java_outer_classname = "GoGoProtos";
option go_package = "github.com/gogo/protobuf/gogoproto";
extend google.protobuf.EnumOptions {
optional bool goproto_enum_prefix = 62001;
optional bool goproto_enum_stringer = 62021;
optional bool enum_stringer = 62022;
optional string enum_customname = 62023;
optional bool enumdecl = 62024;
}
extend google.protobuf.EnumValueOptions {
optional string enumvalue_customname = 66001;
}
extend google.protobuf.FileOptions {
optional bool goproto_getters_all = 63001;
optional bool goproto_enum_prefix_all = 63002;
optional bool goproto_stringer_all = 63003;
optional bool verbose_equal_all = 63004;
optional bool face_all = 63005;
optional bool gostring_all = 63006;
optional bool populate_all = 63007;
optional bool stringer_all = 63008;
optional bool onlyone_all = 63009;
optional bool equal_all = 63013;
optional bool description_all = 63014;
optional bool testgen_all = 63015;
optional bool benchgen_all = 63016;
optional bool marshaler_all = 63017;
optional bool unmarshaler_all = 63018;
optional bool stable_marshaler_all = 63019;
optional bool sizer_all = 63020;
optional bool goproto_enum_stringer_all = 63021;
optional bool enum_stringer_all = 63022;
optional bool unsafe_marshaler_all = 63023;
optional bool unsafe_unmarshaler_all = 63024;
optional bool goproto_extensions_map_all = 63025;
optional bool goproto_unrecognized_all = 63026;
optional bool gogoproto_import = 63027;
optional bool protosizer_all = 63028;
optional bool compare_all = 63029;
optional bool typedecl_all = 63030;
optional bool enumdecl_all = 63031;
optional bool goproto_registration = 63032;
optional bool messagename_all = 63033;
optional bool goproto_sizecache_all = 63034;
optional bool goproto_unkeyed_all = 63035;
}
extend google.protobuf.MessageOptions {
optional bool goproto_getters = 64001;
optional bool goproto_stringer = 64003;
optional bool verbose_equal = 64004;
optional bool face = 64005;
optional bool gostring = 64006;
optional bool populate = 64007;
optional bool stringer = 67008;
optional bool onlyone = 64009;
optional bool equal = 64013;
optional bool description = 64014;
optional bool testgen = 64015;
optional bool benchgen = 64016;
optional bool marshaler = 64017;
optional bool unmarshaler = 64018;
optional bool stable_marshaler = 64019;
optional bool sizer = 64020;
optional bool unsafe_marshaler = 64023;
optional bool unsafe_unmarshaler = 64024;
optional bool goproto_extensions_map = 64025;
optional bool goproto_unrecognized = 64026;
optional bool protosizer = 64028;
optional bool compare = 64029;
optional bool typedecl = 64030;
optional bool messagename = 64033;
optional bool goproto_sizecache = 64034;
optional bool goproto_unkeyed = 64035;
}
extend google.protobuf.FieldOptions {
optional bool nullable = 65001;
optional bool embed = 65002;
optional string customtype = 65003;
optional string customname = 65004;
optional string jsontag = 65005;
optional string moretags = 65006;
optional string casttype = 65007;
optional string castkey = 65008;
optional string castvalue = 65009;
optional bool stdtime = 65010;
optional bool stdduration = 65011;
optional bool wktpointer = 65012;
}
syntax = "proto3";
package base.v1;
import "google/protobuf/timestamp.proto";
import "google/protobuf/any.proto";
import "base/v1/resource.proto";
import "base/v1/meta.proto";
import "base/gogo.proto";
// BatchTx include one batchHash and all original tx contained in batch.
// it will broadcast to nebula over p2p module, and then save in p2p module.
// Amount metaprooftx make a batch tx, and generate a batch_hash,
message BatchTx {
Hash batch_hash = 1 [(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
repeated MetaProofTx txs = 2;
}
\ No newline at end of file
syntax = "proto3";
package base.v1;
import "google/protobuf/timestamp.proto";
import "google/protobuf/any.proto";
import "base/v1/resource.proto";
import "base/v1/eth_tx.proto";
import "base/gogo.proto";
message EthBlockHeader {
Hash parent_hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
Hash uncle_hash = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
Hash block_hash = 3[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
Address miner = 4[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
Hash state_root = 5[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
Hash txs_root = 6[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
Hash receipts_root = 7[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
BigInt block_number = 8[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
Bloom block_bloom = 9;
BigInt difficulty = 10[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
uint64 gas_limit = 11;
uint64 gas_used = 12;
uint64 timestamp = 13;
bytes extra = 14;
Hash mix_hash = 15[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
BigInt block_nonce = 16[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
BigInt base_fee = 17[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message EthBlockBody {
repeated EthTransaction txs = 1;
repeated EthBlockHeader uncles = 2;
}
message EthBlock {
EthBlockHeader header = 1;
repeated EthBlockHeader uncles = 2;
repeated EthTransaction txs = 3;
}
\ No newline at end of file
syntax = "proto3";
package base.v1;
import "google/protobuf/timestamp.proto";
import "google/protobuf/any.proto";
import "base/v1/resource.proto";
import "base/gogo.proto";
option (gogoproto.messagename_all) = true;
message EthTxParam {
Address from = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
Address to = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
uint64 gas = 3;
BigInt gas_price = 4[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
BigInt max_fee_per_gas = 5[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
BigInt max_priority_fee_per_gas = 6[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
BigInt value = 7[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
uint64 nonce = 8;
bytes input = 9;
AccessList accesslist = 10;
BigInt chain_id = 11[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message EthLegacyTx {
uint64 nonce = 1;
BigInt gas_price = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
uint64 gas = 3;
Address to = 4[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
BigInt value = 5[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
bytes data = 6;
BigInt v = 7[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
BigInt r = 8[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
BigInt s = 9[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message EthAccessListTx {
BigInt chain_id = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
uint64 nonce = 2;
BigInt gas_price = 3[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
uint64 gas = 4;
Address to = 5[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
BigInt value = 6[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
bytes data = 7;
AccessList access_list = 8;
BigInt v = 9[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
BigInt r = 10[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
BigInt s = 11[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message EthDynamicFeeTx {
BigInt chain_id = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
uint64 nonce = 2;
BigInt gas_tip_cap = 3[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
BigInt gas_fee_cap = 4[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
uint64 gas = 5;
Address to = 6[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
BigInt value = 7[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
bytes data = 8;
AccessList access_list = 9;
BigInt v = 10[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
BigInt r = 11[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
BigInt s = 12[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message EthTransaction {
google.protobuf.Any tx = 1; // one of EthLegacyTx, EthAccessListTx, EthDynamicFeeTx
}
// EthTxLog reference ethereum Log struct.
message EthTxLog {
Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
repeated Hash topics = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
bytes data = 3;
uint64 block_number = 4;
Hash tx_hash = 5[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
uint32 tx_index = 6;
Hash block_hash = 7[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
uint32 log_index = 8;
bool removed = 9;
}
message EthReceipt {
uint32 type = 1;
bytes root = 2;
uint64 status = 3;
uint64 cumulative_gas_used = 4;
Bloom bloom = 5;
repeated EthTxLog logs = 6;
Hash tx_hash = 7[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
Address contract_address = 8[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
uint64 gas_used = 9;
Hash block_hash = 10[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
BigInt block_number = 11[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
uint32 tx_index = 12;
}
syntax = "proto3";
package base.v1;
import "google/protobuf/timestamp.proto";
import "google/protobuf/any.proto";
import "base/v1/resource.proto";
import "base/gogo.proto";
option (gogoproto.messagename_all) = true;
message MetaProof{
bytes rset = 1;
bytes wset = 2;
bytes proof = 3;
int64 state_block_num = 4;
}
message MetaTxBase {
// tx_type used to type tx.
uint32 tx_type = 1;
BigInt chain_id = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
uint64 nonce = 3;
BigInt gas_price = 4[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
uint64 gas = 5;
Address to = 6[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
BigInt value = 7[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
bytes data = 8;
AccessList access_list = 9;
BigInt v = 10[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
BigInt r = 11[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
BigInt s = 12[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
Address from = 13[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
//google.protobuf.Timestamp receive_time = 14; `protobuf:"bytes,1,opt,name=Name,proto3"`
// expire block used to ignore execute tx when it is packaged in expired_block.
BigInt expired_block = 15[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
Hash tx_hash = 16[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
}
message MetaProofTx {
MetaTxBase base = 1;
MetaProof proof = 2;
}
message MetaTransaction {
google.protobuf.Any tx = 1;
}
message MetaBlockHeader {
Hash parent_hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
Hash block_hash = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
Address miner = 3[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
Hash state_root = 4[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
Hash txs_root = 5[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
Hash receipts_root = 6[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
BigInt block_number = 7[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
Bloom block_bloom = 8;
uint64 gas_limit = 9;
uint64 gas_used = 10;
uint64 timestamp = 11;
bytes extra = 12;
}
message MetaBlockBody {
repeated MetaTransaction txs = 1;
}
message MetaBlock {
MetaBlockHeader header = 1;
repeated MetaTransaction txs = 2;
}
message MetaTxLog {
Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
repeated Hash topics = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
bytes data = 3;
uint64 block_number = 4;
Hash tx_hash = 5[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
uint32 tx_index = 6;
Hash block_hash = 7[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
uint32 log_index = 8;
bool removed = 9;
}
message MetaReceipt {
uint32 type = 1;
bytes root = 2;
uint64 status = 3;
uint64 cumulative_gas_used = 4;
Bloom bloom = 5;
repeated MetaTxLog logs = 6;
Hash tx_hash = 7[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
Address contract_address = 8[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
uint64 gas_used = 9;
Hash block_hash = 10[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
BigInt block_number = 11[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
uint32 tx_index = 12;
}
\ No newline at end of file
syntax = "proto3";
package base.v1;
import "google/protobuf/descriptor.proto";
extend google.protobuf.FieldOptions {
uint32 bytes_size = 50000; // define bytes data size.
}
\ No newline at end of file
syntax = "proto3";
package base.v1;
import "google/protobuf/timestamp.proto";
import "google/protobuf/any.proto";
import "base/gogo.proto";
// import "google/protobuf/descriptor.proto";
// import "github.com/gogo/protobuf/gogoproto/gogo.proto";
// import "base/v1/options.proto";
message Bytes32 {
bytes data = 1;
}
message BigInt {
bytes data = 1;
// bytes data = 1 [(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaProtocol/custom/types.BigInt"][(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message Hash {
bytes hash = 1;
}
message Address {
bytes address = 1;
}
message RLPData {
bytes data = 1;
}
message Account {
Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
uint64 nonce = 2;
BigInt balance = 3 [(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
Hash state_root = 4[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
}
message Bloom {
bytes data = 1;
}
message AccessTuple {
Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
repeated Hash storage_keys = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
}
message AccessList {
repeated AccessTuple access_list = 1;
}
\ No newline at end of file
version: v1
deps:
- buf.build/gogo/protobuf
# - buf.build/googleapis/googleapis
# - buf.build/acme/paymentapis
breaking:
use:
- FILE
lint:
use:
- DEFAULT
goos: linux
goarch: amd64
pkg: github.com/CaduceusMetaverseProtocol/MetaProtocol/benchmark
cpu: Intel(R) Xeon(R) Platinum 8275CL CPU @ 3.00GHz
BenchmarkRepeated
BenchmarkRepeated/input_size_100
BenchmarkRepeated/input_size_100-8 5354 215812 ns/op 62.78 MB/s 4634 tps 253875 B/op 2123 allocs/op
BenchmarkRepeated/input_size_100-8 5103 212988 ns/op 63.61 MB/s 4695 tps 253511 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5265 214639 ns/op 63.12 MB/s 4659 tps 253505 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5073 207863 ns/op 65.18 MB/s 4811 tps 253515 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5172 210654 ns/op 64.32 MB/s 4747 tps 253508 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5241 211967 ns/op 63.92 MB/s 4718 tps 253568 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5097 211979 ns/op 63.92 MB/s 4717 tps 253601 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5074 207968 ns/op 65.15 MB/s 4808 tps 253607 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5169 219785 ns/op 61.65 MB/s 4550 tps 253607 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5269 210668 ns/op 64.31 MB/s 4747 tps 253596 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5270 209685 ns/op 64.62 MB/s 4769 tps 253599 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5199 215535 ns/op 62.86 MB/s 4640 tps 253592 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5146 206768 ns/op 65.53 MB/s 4836 tps 253596 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5088 209751 ns/op 64.60 MB/s 4768 tps 253608 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5084 209739 ns/op 64.60 MB/s 4768 tps 253582 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5262 213463 ns/op 63.47 MB/s 4685 tps 253604 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5124 207937 ns/op 65.16 MB/s 4809 tps 253605 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5106 213187 ns/op 63.55 MB/s 4691 tps 253607 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5467 216637 ns/op 62.54 MB/s 4616 tps 253647 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5149 210551 ns/op 64.35 MB/s 4749 tps 253604 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 4962 212257 ns/op 63.83 MB/s 4711 tps 253599 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5282 202462 ns/op 66.92 MB/s 4939 tps 253597 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 4993 214361 ns/op 63.21 MB/s 4665 tps 253604 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 4963 207333 ns/op 65.35 MB/s 4823 tps 253605 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 4988 213317 ns/op 63.52 MB/s 4688 tps 253600 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5234 207565 ns/op 65.28 MB/s 4818 tps 253593 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5157 211094 ns/op 64.18 MB/s 4737 tps 253604 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5148 206289 ns/op 65.68 MB/s 4848 tps 253600 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5114 208338 ns/op 65.03 MB/s 4800 tps 253595 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5200 213336 ns/op 63.51 MB/s 4687 tps 253593 B/op 2122 allocs/op
BenchmarkRepeated/input_size_200
BenchmarkRepeated/input_size_200-8 3937 278136 ns/op 97.26 MB/s 3595 tps 365232 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3800 281287 ns/op 96.17 MB/s 3555 tps 365247 B/op 3624 allocs/op
BenchmarkRepeated/input_size_200-8 4460 283111 ns/op 95.55 MB/s 3532 tps 365207 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3898 286982 ns/op 94.26 MB/s 3485 tps 365228 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3838 288482 ns/op 93.77 MB/s 3466 tps 365241 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3643 278941 ns/op 96.98 MB/s 3585 tps 365221 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3735 290439 ns/op 93.14 MB/s 3443 tps 365231 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3754 284573 ns/op 95.06 MB/s 3514 tps 365250 B/op 3624 allocs/op
BenchmarkRepeated/input_size_200-8 3739 279416 ns/op 96.81 MB/s 3579 tps 365239 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3763 285826 ns/op 94.64 MB/s 3499 tps 365238 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3865 285503 ns/op 94.75 MB/s 3503 tps 365238 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3800 286599 ns/op 94.39 MB/s 3489 tps 365228 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 4105 286243 ns/op 94.50 MB/s 3494 tps 365236 B/op 3624 allocs/op
BenchmarkRepeated/input_size_200-8 3880 290468 ns/op 93.13 MB/s 3443 tps 365239 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3663 274201 ns/op 98.65 MB/s 3647 tps 365224 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3688 283713 ns/op 95.35 MB/s 3525 tps 365227 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3729 289573 ns/op 93.42 MB/s 3453 tps 365242 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3763 287146 ns/op 94.21 MB/s 3483 tps 365241 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3786 275284 ns/op 98.27 MB/s 3633 tps 365228 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 4168 278086 ns/op 97.28 MB/s 3596 tps 365228 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3760 285484 ns/op 94.75 MB/s 3503 tps 365232 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3697 287611 ns/op 94.05 MB/s 3477 tps 365233 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3830 276699 ns/op 97.76 MB/s 3614 tps 365246 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 4045 287549 ns/op 94.07 MB/s 3478 tps 365250 B/op 3624 allocs/op
BenchmarkRepeated/input_size_200-8 3804 283904 ns/op 95.28 MB/s 3522 tps 365237 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3800 289140 ns/op 93.56 MB/s 3459 tps 365237 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3903 284960 ns/op 94.93 MB/s 3509 tps 365222 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3692 285281 ns/op 94.82 MB/s 3505 tps 365244 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3838 280844 ns/op 96.32 MB/s 3561 tps 365225 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3873 278410 ns/op 97.16 MB/s 3592 tps 365223 B/op 3623 allocs/op
BenchmarkRepeated/input_size_500
BenchmarkRepeated/input_size_500-8 2113 511509 ns/op 132.06 MB/s 1955 tps 701715 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2186 521739 ns/op 129.47 MB/s 1917 tps 701695 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2162 518347 ns/op 130.32 MB/s 1929 tps 701701 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2169 516949 ns/op 130.67 MB/s 1934 tps 701694 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2107 513584 ns/op 131.53 MB/s 1947 tps 701712 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2168 528633 ns/op 127.78 MB/s 1892 tps 701708 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2200 518066 ns/op 130.39 MB/s 1930 tps 701693 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2179 506847 ns/op 133.28 MB/s 1973 tps 701713 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2156 520904 ns/op 129.68 MB/s 1920 tps 701716 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 1935 529816 ns/op 127.50 MB/s 1887 tps 701707 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2154 516084 ns/op 130.89 MB/s 1938 tps 701707 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 1882 535006 ns/op 125.33 MB/s 1869 tps 701711 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2098 520634 ns/op 129.75 MB/s 1921 tps 701695 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2304 534631 ns/op 126.35 MB/s 1870 tps 701694 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2067 512192 ns/op 131.89 MB/s 1952 tps 701727 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2215 530709 ns/op 127.28 MB/s 1884 tps 701697 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2134 509996 ns/op 132.45 MB/s 1961 tps 701698 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2268 521585 ns/op 129.51 MB/s 1917 tps 701814 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2259 530969 ns/op 127.22 MB/s 1883 tps 701819 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2139 529046 ns/op 127.68 MB/s 1890 tps 701835 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2295 515587 ns/op 131.02 MB/s 1940 tps 701807 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2124 520017 ns/op 129.90 MB/s 1923 tps 701816 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2119 514793 ns/op 131.22 MB/s 1943 tps 701820 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2299 532952 ns/op 126.75 MB/s 1876 tps 701797 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2154 510942 ns/op 132.21 MB/s 1957 tps 701825 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2118 530636 ns/op 127.30 MB/s 1885 tps 701822 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2296 526603 ns/op 128.28 MB/s 1899 tps 701814 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2182 515408 ns/op 131.06 MB/s 1940 tps 701824 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2191 526906 ns/op 128.20 MB/s 1898 tps 701821 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2154 518881 ns/op 130.19 MB/s 1927 tps 701813 B/op 8144 allocs/op
BenchmarkRepeated/input_size_1000
BenchmarkRepeated/input_size_1000-8 1329 898604 ns/op 150.29 MB/s 1113 tps 1226650 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 1291 900556 ns/op 149.96 MB/s 1110 tps 1226636 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 1369 898981 ns/op 150.23 MB/s 1112 tps 1226649 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 1147 898222 ns/op 150.35 MB/s 1113 tps 1226639 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 1302 893215 ns/op 151.20 MB/s 1120 tps 1226645 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 1261 898420 ns/op 150.32 MB/s 1113 tps 1226655 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 1334 901683 ns/op 149.78 MB/s 1109 tps 1226645 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 1178 913785 ns/op 147.79 MB/s 1094 tps 1226653 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 1323 1005911 ns/op 134.26 MB/s 994.1 tps 1226645 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 1069 1040527 ns/op 129.79 MB/s 961.0 tps 1226682 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 1137 1038156 ns/op 130.09 MB/s 963.2 tps 1226652 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 1159 1027091 ns/op 131.49 MB/s 973.6 tps 1226652 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 1165 1054961 ns/op 128.02 MB/s 947.9 tps 1226682 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 1051 1035192 ns/op 130.46 MB/s 966.0 tps 1226656 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 981 1041401 ns/op 129.68 MB/s 960.2 tps 1226653 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 1134 1037511 ns/op 130.17 MB/s 963.8 tps 1226632 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 969 1038856 ns/op 130.00 MB/s 962.6 tps 1226699 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 1052 1049612 ns/op 128.67 MB/s 952.7 tps 1226660 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 1158 1024421 ns/op 131.83 MB/s 976.1 tps 1226658 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 982 1045569 ns/op 129.17 MB/s 956.4 tps 1226668 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 1080 1041561 ns/op 129.66 MB/s 960.1 tps 1226716 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 1114 1015032 ns/op 133.05 MB/s 985.2 tps 1226665 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 1144 1028838 ns/op 131.27 MB/s 972.0 tps 1226662 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 1150 1041181 ns/op 129.71 MB/s 960.4 tps 1226647 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 1063 1045331 ns/op 129.19 MB/s 956.6 tps 1226705 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 937 1067843 ns/op 126.47 MB/s 936.4 tps 1226674 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 1122 1045034 ns/op 129.23 MB/s 956.9 tps 1226685 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 1222 1019449 ns/op 132.47 MB/s 980.9 tps 1226652 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 1051 1034277 ns/op 130.58 MB/s 966.9 tps 1226679 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 1192 1032811 ns/op 130.76 MB/s 968.2 tps 1226648 B/op 15647 allocs/op
BenchmarkRepeated/input_size_2000
BenchmarkRepeated/input_size_2000-8 565 1922587 ns/op 140.46 MB/s 520.1 tps 2276792 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 554 1940279 ns/op 139.18 MB/s 515.4 tps 2276791 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 525 1940614 ns/op 139.16 MB/s 515.3 tps 2276830 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 547 1960243 ns/op 137.76 MB/s 510.1 tps 2276815 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 520 1973390 ns/op 136.85 MB/s 506.7 tps 2276876 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 537 1922480 ns/op 140.47 MB/s 520.2 tps 2276779 B/op 30668 allocs/op
BenchmarkRepeated/input_size_2000-8 544 1938236 ns/op 139.33 MB/s 515.9 tps 2276829 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 537 1933208 ns/op 139.69 MB/s 517.3 tps 2276829 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 546 1929926 ns/op 139.93 MB/s 518.1 tps 2276824 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 550 2019083 ns/op 133.75 MB/s 495.3 tps 2276864 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 568 2026875 ns/op 133.24 MB/s 493.4 tps 2276768 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 684 1654367 ns/op 163.24 MB/s 604.5 tps 2276766 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 702 1630997 ns/op 165.57 MB/s 613.1 tps 2276743 B/op 30668 allocs/op
BenchmarkRepeated/input_size_2000-8 646 1675996 ns/op 161.13 MB/s 596.7 tps 2276806 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 627 1709104 ns/op 158.01 MB/s 585.1 tps 2276789 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 632 1701475 ns/op 158.72 MB/s 587.7 tps 2276716 B/op 30668 allocs/op
BenchmarkRepeated/input_size_2000-8 606 1676377 ns/op 161.09 MB/s 596.5 tps 2276768 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 638 1690357 ns/op 159.76 MB/s 591.6 tps 2276769 B/op 30668 allocs/op
BenchmarkRepeated/input_size_2000-8 624 1653480 ns/op 163.32 MB/s 604.8 tps 2276753 B/op 30668 allocs/op
BenchmarkRepeated/input_size_2000-8 642 1697866 ns/op 159.05 MB/s 589.0 tps 2276809 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 613 1705669 ns/op 158.33 MB/s 586.3 tps 2276694 B/op 30668 allocs/op
BenchmarkRepeated/input_size_2000-8 616 1693920 ns/op 159.42 MB/s 590.3 tps 2276791 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 662 1621707 ns/op 166.52 MB/s 616.6 tps 2276734 B/op 30668 allocs/op
BenchmarkRepeated/input_size_2000-8 596 1705522 ns/op 158.34 MB/s 586.3 tps 2276805 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 628 1702589 ns/op 158.61 MB/s 587.3 tps 2276721 B/op 30668 allocs/op
BenchmarkRepeated/input_size_2000-8 634 1699037 ns/op 158.94 MB/s 588.6 tps 2276861 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 627 1687068 ns/op 160.07 MB/s 592.7 tps 2276818 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 649 1670580 ns/op 161.65 MB/s 598.6 tps 2276826 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 620 1663860 ns/op 162.30 MB/s 601.0 tps 2276715 B/op 30668 allocs/op
BenchmarkRepeated/input_size_2000-8 650 1666700 ns/op 162.03 MB/s 600.0 tps 2276741 B/op 30668 allocs/op
BenchmarkRepeated/input_size_5000
BenchmarkRepeated/input_size_5000-8 282 4006665 ns/op 168.48 MB/s 249.6 tps 5476025 B/op 75714 allocs/op
BenchmarkRepeated/input_size_5000-8 284 3969123 ns/op 170.08 MB/s 251.9 tps 5475993 B/op 75712 allocs/op
BenchmarkRepeated/input_size_5000-8 280 3890434 ns/op 173.52 MB/s 257.0 tps 5475938 B/op 75712 allocs/op
BenchmarkRepeated/input_size_5000-8 277 3939928 ns/op 171.34 MB/s 253.8 tps 5475955 B/op 75712 allocs/op
BenchmarkRepeated/input_size_5000-8 282 4087040 ns/op 165.17 MB/s 244.7 tps 5475871 B/op 75712 allocs/op
BenchmarkRepeated/input_size_5000-8 276 3943437 ns/op 171.18 MB/s 253.6 tps 5476066 B/op 75713 allocs/op
BenchmarkRepeated/input_size_5000-8 272 3949893 ns/op 170.90 MB/s 253.2 tps 5475888 B/op 75712 allocs/op
BenchmarkRepeated/input_size_5000-8 280 4038933 ns/op 167.14 MB/s 247.6 tps 5476012 B/op 75712 allocs/op
BenchmarkRepeated/input_size_5000-8 283 4013566 ns/op 168.19 MB/s 249.1 tps 5475944 B/op 75710 allocs/op
BenchmarkRepeated/input_size_5000-8 283 4002996 ns/op 168.64 MB/s 249.8 tps 5476009 B/op 75712 allocs/op
BenchmarkRepeated/input_size_5000-8 292 3965574 ns/op 170.23 MB/s 252.2 tps 5475859 B/op 75712 allocs/op
BenchmarkRepeated/input_size_5000-8 278 4037635 ns/op 167.19 MB/s 247.7 tps 5476151 B/op 75713 allocs/op
BenchmarkRepeated/input_size_5000-8 272 4007171 ns/op 168.46 MB/s 249.5 tps 5475890 B/op 75712 allocs/op
BenchmarkRepeated/input_size_5000-8 277 4025983 ns/op 167.67 MB/s 248.4 tps 5475961 B/op 75712 allocs/op
BenchmarkRepeated/input_size_5000-8 277 3981942 ns/op 169.53 MB/s 251.1 tps 5476117 B/op 75714 allocs/op
BenchmarkRepeated/input_size_5000-8 271 4033490 ns/op 167.36 MB/s 247.9 tps 5476102 B/op 75713 allocs/op
BenchmarkRepeated/input_size_5000-8 276 3962968 ns/op 170.34 MB/s 252.3 tps 5475995 B/op 75712 allocs/op
BenchmarkRepeated/input_size_5000-8 276 4019756 ns/op 167.93 MB/s 248.8 tps 5476059 B/op 75713 allocs/op
BenchmarkRepeated/input_size_5000-8 282 3966737 ns/op 170.18 MB/s 252.1 tps 5476030 B/op 75713 allocs/op
BenchmarkRepeated/input_size_5000-8 264 4086386 ns/op 165.20 MB/s 244.7 tps 5475991 B/op 75712 allocs/op
BenchmarkRepeated/input_size_5000-8 283 4031156 ns/op 167.46 MB/s 248.1 tps 5475888 B/op 75711 allocs/op
BenchmarkRepeated/input_size_5000-8 288 3938892 ns/op 171.38 MB/s 253.9 tps 5475912 B/op 75713 allocs/op
BenchmarkRepeated/input_size_5000-8 279 3948239 ns/op 170.98 MB/s 253.3 tps 5475994 B/op 75712 allocs/op
BenchmarkRepeated/input_size_5000-8 288 3928843 ns/op 171.82 MB/s 254.5 tps 5475983 B/op 75712 allocs/op
BenchmarkRepeated/input_size_5000-8 279 4007579 ns/op 168.44 MB/s 249.5 tps 5475878 B/op 75711 allocs/op
BenchmarkRepeated/input_size_5000-8 278 3947619 ns/op 171.00 MB/s 253.3 tps 5475974 B/op 75713 allocs/op
BenchmarkRepeated/input_size_5000-8 273 3970411 ns/op 170.02 MB/s 251.9 tps 5475976 B/op 75712 allocs/op
BenchmarkRepeated/input_size_5000-8 277 3939248 ns/op 171.37 MB/s 253.9 tps 5476123 B/op 75714 allocs/op
BenchmarkRepeated/input_size_5000-8 283 4027695 ns/op 167.60 MB/s 248.3 tps 5476121 B/op 75713 allocs/op
BenchmarkRepeated/input_size_5000-8 280 3951109 ns/op 170.85 MB/s 253.1 tps 5475884 B/op 75712 allocs/op
BenchmarkRepeated/input_size_10000
BenchmarkRepeated/input_size_10000-8 148 7902491 ns/op 170.84 MB/s 126.5 tps 10773878 B/op 150756 allocs/op
BenchmarkRepeated/input_size_10000-8 144 7608680 ns/op 177.44 MB/s 131.4 tps 10773718 B/op 150760 allocs/op
BenchmarkRepeated/input_size_10000-8 147 7851093 ns/op 171.96 MB/s 127.4 tps 10773822 B/op 150759 allocs/op
BenchmarkRepeated/input_size_10000-8 151 7860893 ns/op 171.74 MB/s 127.2 tps 10773835 B/op 150761 allocs/op
BenchmarkRepeated/input_size_10000-8 146 7678551 ns/op 175.82 MB/s 130.2 tps 10773715 B/op 150758 allocs/op
BenchmarkRepeated/input_size_10000-8 145 7805639 ns/op 172.96 MB/s 128.1 tps 10773712 B/op 150758 allocs/op
BenchmarkRepeated/input_size_10000-8 150 7898258 ns/op 170.93 MB/s 126.6 tps 10774057 B/op 150760 allocs/op
BenchmarkRepeated/input_size_10000-8 145 7551867 ns/op 178.77 MB/s 132.4 tps 10773744 B/op 150758 allocs/op
BenchmarkRepeated/input_size_10000-8 150 7719153 ns/op 174.90 MB/s 129.5 tps 10773737 B/op 150757 allocs/op
BenchmarkRepeated/input_size_10000-8 146 7780850 ns/op 173.51 MB/s 128.5 tps 10773708 B/op 150757 allocs/op
BenchmarkRepeated/input_size_10000-8 152 7793085 ns/op 173.24 MB/s 128.3 tps 10773980 B/op 150762 allocs/op
BenchmarkRepeated/input_size_10000-8 148 7682008 ns/op 175.74 MB/s 130.2 tps 10773614 B/op 150756 allocs/op
BenchmarkRepeated/input_size_10000-8 145 7613925 ns/op 177.31 MB/s 131.3 tps 10773793 B/op 150759 allocs/op
BenchmarkRepeated/input_size_10000-8 141 7598050 ns/op 177.68 MB/s 131.6 tps 10773946 B/op 150761 allocs/op
BenchmarkRepeated/input_size_10000-8 139 7740425 ns/op 174.42 MB/s 129.2 tps 10773684 B/op 150757 allocs/op
BenchmarkRepeated/input_size_10000-8 145 7790216 ns/op 173.30 MB/s 128.4 tps 10773654 B/op 150759 allocs/op
BenchmarkRepeated/input_size_10000-8 147 7732761 ns/op 174.59 MB/s 129.3 tps 10773894 B/op 150759 allocs/op
BenchmarkRepeated/input_size_10000-8 150 7670079 ns/op 176.02 MB/s 130.4 tps 10773878 B/op 150758 allocs/op
BenchmarkRepeated/input_size_10000-8 144 7671900 ns/op 175.97 MB/s 130.3 tps 10773733 B/op 150757 allocs/op
BenchmarkRepeated/input_size_10000-8 148 7787514 ns/op 173.36 MB/s 128.4 tps 10773792 B/op 150758 allocs/op
BenchmarkRepeated/input_size_10000-8 148 7625248 ns/op 177.05 MB/s 131.1 tps 10773829 B/op 150760 allocs/op
BenchmarkRepeated/input_size_10000-8 144 7695998 ns/op 175.42 MB/s 129.9 tps 10773778 B/op 150759 allocs/op
BenchmarkRepeated/input_size_10000-8 146 7847920 ns/op 172.03 MB/s 127.4 tps 10773708 B/op 150760 allocs/op
BenchmarkRepeated/input_size_10000-8 150 7661056 ns/op 176.22 MB/s 130.5 tps 10773908 B/op 150761 allocs/op
BenchmarkRepeated/input_size_10000-8 147 7681714 ns/op 175.75 MB/s 130.2 tps 10773802 B/op 150759 allocs/op
BenchmarkRepeated/input_size_10000-8 147 7708744 ns/op 175.13 MB/s 129.7 tps 10773870 B/op 150758 allocs/op
BenchmarkRepeated/input_size_10000-8 147 7836468 ns/op 172.28 MB/s 127.6 tps 10773777 B/op 150759 allocs/op
BenchmarkRepeated/input_size_10000-8 150 7579211 ns/op 178.13 MB/s 131.9 tps 10773939 B/op 150762 allocs/op
BenchmarkRepeated/input_size_10000-8 150 8039020 ns/op 167.94 MB/s 124.4 tps 10773973 B/op 150763 allocs/op
BenchmarkRepeated/input_size_10000-8 146 7542214 ns/op 179.00 MB/s 132.6 tps 10773884 B/op 150760 allocs/op
BenchmarkRepeated/input_size_20000
BenchmarkRepeated/input_size_20000-8 76 15019743 ns/op 179.77 MB/s 66.58 tps 21392320 B/op 300817 allocs/op
BenchmarkRepeated/input_size_20000-8 75 14834201 ns/op 182.02 MB/s 67.41 tps 21392330 B/op 300817 allocs/op
BenchmarkRepeated/input_size_20000-8 75 14859530 ns/op 181.71 MB/s 67.30 tps 21392378 B/op 300824 allocs/op
BenchmarkRepeated/input_size_20000-8 75 14829772 ns/op 182.07 MB/s 67.43 tps 21392318 B/op 300819 allocs/op
BenchmarkRepeated/input_size_20000-8 75 15385540 ns/op 175.49 MB/s 65.00 tps 21392001 B/op 300819 allocs/op
BenchmarkRepeated/input_size_20000-8 60 17557242 ns/op 153.79 MB/s 56.96 tps 21391900 B/op 300813 allocs/op
BenchmarkRepeated/input_size_20000-8 64 17082625 ns/op 158.06 MB/s 58.54 tps 21392561 B/op 300823 allocs/op
BenchmarkRepeated/input_size_20000-8 68 16723838 ns/op 161.45 MB/s 59.79 tps 21392289 B/op 300815 allocs/op
BenchmarkRepeated/input_size_20000-8 66 16845576 ns/op 160.28 MB/s 59.36 tps 21392700 B/op 300825 allocs/op
BenchmarkRepeated/input_size_20000-8 66 16788788 ns/op 160.82 MB/s 59.56 tps 21392020 B/op 300818 allocs/op
BenchmarkRepeated/input_size_20000-8 68 16833238 ns/op 160.40 MB/s 59.41 tps 21392362 B/op 300819 allocs/op
BenchmarkRepeated/input_size_20000-8 67 17459462 ns/op 154.65 MB/s 57.27 tps 21391939 B/op 300826 allocs/op
BenchmarkRepeated/input_size_20000-8 66 15359042 ns/op 175.80 MB/s 65.11 tps 21392334 B/op 300822 allocs/op
BenchmarkRepeated/input_size_20000-8 76 14693705 ns/op 183.76 MB/s 68.05 tps 21392639 B/op 300829 allocs/op
BenchmarkRepeated/input_size_20000-8 76 14904969 ns/op 181.15 MB/s 67.09 tps 21392528 B/op 300819 allocs/op
BenchmarkRepeated/input_size_20000-8 76 15466058 ns/op 174.58 MB/s 64.66 tps 21391954 B/op 300809 allocs/op
BenchmarkRepeated/input_size_20000-8 78 15009605 ns/op 179.89 MB/s 66.62 tps 21391837 B/op 300818 allocs/op
BenchmarkRepeated/input_size_20000-8 73 15080814 ns/op 179.04 MB/s 66.31 tps 21392229 B/op 300822 allocs/op
BenchmarkRepeated/input_size_20000-8 75 14577368 ns/op 185.22 MB/s 68.60 tps 21392148 B/op 300822 allocs/op
BenchmarkRepeated/input_size_20000-8 75 14973644 ns/op 180.32 MB/s 66.78 tps 21392388 B/op 300823 allocs/op
BenchmarkRepeated/input_size_20000-8 75 14885947 ns/op 181.38 MB/s 67.18 tps 21392154 B/op 300820 allocs/op
BenchmarkRepeated/input_size_20000-8 78 14863245 ns/op 181.66 MB/s 67.28 tps 21392635 B/op 300822 allocs/op
BenchmarkRepeated/input_size_20000-8 76 15034778 ns/op 179.59 MB/s 66.51 tps 21392140 B/op 300821 allocs/op
BenchmarkRepeated/input_size_20000-8 76 14744601 ns/op 183.12 MB/s 67.82 tps 21392344 B/op 300815 allocs/op
BenchmarkRepeated/input_size_20000-8 76 14757377 ns/op 182.96 MB/s 67.76 tps 21392313 B/op 300828 allocs/op
BenchmarkRepeated/input_size_20000-8 73 14871576 ns/op 181.56 MB/s 67.24 tps 21392077 B/op 300814 allocs/op
BenchmarkRepeated/input_size_20000-8 74 14826698 ns/op 180.76 MB/s 67.44 tps 21342890 B/op 300808 allocs/op
BenchmarkRepeated/input_size_20000-8 74 14833809 ns/op 182.02 MB/s 67.41 tps 21392228 B/op 300817 allocs/op
BenchmarkRepeated/input_size_20000-8 80 14829076 ns/op 182.08 MB/s 67.43 tps 21392166 B/op 300818 allocs/op
BenchmarkRepeated/input_size_20000-8 75 15022027 ns/op 179.74 MB/s 66.57 tps 21392118 B/op 300815 allocs/op
PASS
ok github.com/CaduceusMetaverseProtocol/MetaProtocol/benchmark 342.727s
goos: linux
goarch: amd64
pkg: github.com/CaduceusMetaverseProtocol/MetaProtocol/benchmark
cpu: Intel(R) Xeon(R) Platinum 8275CL CPU @ 3.00GHz
BenchmarkRepeated
BenchmarkRepeated/input_size_100
BenchmarkRepeated/input_size_100-8 5977 184548 ns/op 47.68 MB/s 174664 B/op 827 allocs/op
BenchmarkRepeated/input_size_100-8 6340 186595 ns/op 47.16 MB/s 174422 B/op 826 allocs/op
BenchmarkRepeated/input_size_100-8 5632 184942 ns/op 47.58 MB/s 174312 B/op 825 allocs/op
BenchmarkRepeated/input_size_100-8 5457 185751 ns/op 47.38 MB/s 174402 B/op 826 allocs/op
BenchmarkRepeated/input_size_100-8 6044 179378 ns/op 49.06 MB/s 174451 B/op 826 allocs/op
BenchmarkRepeated/input_size_100-8 6381 186335 ns/op 47.23 MB/s 174457 B/op 826 allocs/op
BenchmarkRepeated/input_size_100-8 6573 182216 ns/op 48.29 MB/s 174486 B/op 826 allocs/op
BenchmarkRepeated/input_size_100-8 5512 183640 ns/op 47.92 MB/s 174449 B/op 826 allocs/op
BenchmarkRepeated/input_size_100-8 6529 182776 ns/op 48.15 MB/s 174455 B/op 826 allocs/op
BenchmarkRepeated/input_size_100-8 5996 188096 ns/op 46.78 MB/s 174460 B/op 826 allocs/op
BenchmarkRepeated/input_size_200
BenchmarkRepeated/input_size_200-8 4570 235086 ns/op 74.87 MB/s 206761 B/op 1029 allocs/op
BenchmarkRepeated/input_size_200-8 4668 230969 ns/op 76.20 MB/s 206756 B/op 1029 allocs/op
BenchmarkRepeated/input_size_200-8 4944 240535 ns/op 73.17 MB/s 206767 B/op 1029 allocs/op
BenchmarkRepeated/input_size_200-8 4610 230567 ns/op 76.33 MB/s 206760 B/op 1029 allocs/op
BenchmarkRepeated/input_size_200-8 5331 224272 ns/op 78.48 MB/s 206757 B/op 1029 allocs/op
BenchmarkRepeated/input_size_200-8 4593 238365 ns/op 73.84 MB/s 206758 B/op 1029 allocs/op
BenchmarkRepeated/input_size_200-8 4935 230521 ns/op 76.35 MB/s 206762 B/op 1029 allocs/op
BenchmarkRepeated/input_size_200-8 4530 239932 ns/op 73.35 MB/s 206764 B/op 1029 allocs/op
BenchmarkRepeated/input_size_200-8 4711 228163 ns/op 77.14 MB/s 206759 B/op 1029 allocs/op
BenchmarkRepeated/input_size_200-8 4570 240760 ns/op 73.10 MB/s 206759 B/op 1029 allocs/op
BenchmarkRepeated/input_size_500
BenchmarkRepeated/input_size_500-8 3246 385988 ns/op 113.99 MB/s 294310 B/op 1651 allocs/op
BenchmarkRepeated/input_size_500-8 3142 377949 ns/op 116.42 MB/s 294327 B/op 1652 allocs/op
BenchmarkRepeated/input_size_500-8 3004 381286 ns/op 115.40 MB/s 294316 B/op 1652 allocs/op
BenchmarkRepeated/input_size_500-8 3174 384338 ns/op 114.48 MB/s 294321 B/op 1651 allocs/op
BenchmarkRepeated/input_size_500-8 3214 397752 ns/op 110.62 MB/s 294318 B/op 1651 allocs/op
BenchmarkRepeated/input_size_500-8 2775 380948 ns/op 115.50 MB/s 294328 B/op 1652 allocs/op
BenchmarkRepeated/input_size_500-8 3151 400837 ns/op 109.77 MB/s 294279 B/op 1650 allocs/op
BenchmarkRepeated/input_size_500-8 3241 379699 ns/op 115.88 MB/s 294324 B/op 1651 allocs/op
BenchmarkRepeated/input_size_500-8 3141 388943 ns/op 113.13 MB/s 294326 B/op 1652 allocs/op
BenchmarkRepeated/input_size_500-8 3166 453102 ns/op 97.11 MB/s 294331 B/op 1651 allocs/op
BenchmarkRepeated/input_size_1000
BenchmarkRepeated/input_size_1000-8 2090 607913 ns/op 144.76 MB/s 427922 B/op 2652 allocs/op
BenchmarkRepeated/input_size_1000-8 1924 624791 ns/op 140.85 MB/s 427907 B/op 2651 allocs/op
BenchmarkRepeated/input_size_1000-8 1938 622011 ns/op 141.48 MB/s 427925 B/op 2652 allocs/op
BenchmarkRepeated/input_size_1000-8 2079 620722 ns/op 141.77 MB/s 427922 B/op 2652 allocs/op
BenchmarkRepeated/input_size_1000-8 1902 618467 ns/op 142.29 MB/s 427907 B/op 2651 allocs/op
BenchmarkRepeated/input_size_1000-8 2066 632389 ns/op 139.15 MB/s 427929 B/op 2652 allocs/op
BenchmarkRepeated/input_size_1000-8 2050 624769 ns/op 140.85 MB/s 427927 B/op 2652 allocs/op
BenchmarkRepeated/input_size_1000-8 1622 638226 ns/op 137.88 MB/s 427949 B/op 2652 allocs/op
BenchmarkRepeated/input_size_1000-8 2047 627494 ns/op 140.24 MB/s 427901 B/op 2651 allocs/op
BenchmarkRepeated/input_size_1000-8 1933 622538 ns/op 141.36 MB/s 427904 B/op 2651 allocs/op
BenchmarkRepeated/input_size_2000
BenchmarkRepeated/input_size_2000-8 1189 1076117 ns/op 163.55 MB/s 695546 B/op 4670 allocs/op
BenchmarkRepeated/input_size_2000-8 920 1097923 ns/op 160.30 MB/s 695559 B/op 4670 allocs/op
BenchmarkRepeated/input_size_2000-8 1086 1083484 ns/op 162.44 MB/s 695515 B/op 4670 allocs/op
BenchmarkRepeated/input_size_2000-8 986 1110391 ns/op 158.50 MB/s 695582 B/op 4671 allocs/op
BenchmarkRepeated/input_size_2000-8 1065 1088964 ns/op 161.62 MB/s 695475 B/op 4669 allocs/op
BenchmarkRepeated/input_size_2000-8 1020 1087322 ns/op 161.87 MB/s 695576 B/op 4671 allocs/op
BenchmarkRepeated/input_size_2000-8 1032 1096346 ns/op 160.53 MB/s 695542 B/op 4670 allocs/op
BenchmarkRepeated/input_size_2000-8 932 1107664 ns/op 158.89 MB/s 695565 B/op 4670 allocs/op
BenchmarkRepeated/input_size_2000-8 1044 1079289 ns/op 163.07 MB/s 695554 B/op 4670 allocs/op
BenchmarkRepeated/input_size_2000-8 964 1113049 ns/op 158.12 MB/s 695558 B/op 4670 allocs/op
BenchmarkRepeated/input_size_5000
BenchmarkRepeated/input_size_5000-8 462 2468051 ns/op 178.28 MB/s 1514726 B/op 10709 allocs/op
BenchmarkRepeated/input_size_5000-8 442 2503170 ns/op 175.78 MB/s 1514761 B/op 10709 allocs/op
BenchmarkRepeated/input_size_5000-8 428 2472007 ns/op 177.99 MB/s 1514724 B/op 10709 allocs/op
BenchmarkRepeated/input_size_5000-8 427 2460562 ns/op 178.82 MB/s 1514737 B/op 10708 allocs/op
BenchmarkRepeated/input_size_5000-8 430 2490331 ns/op 176.68 MB/s 1514776 B/op 10709 allocs/op
BenchmarkRepeated/input_size_5000-8 447 2472108 ns/op 177.99 MB/s 1514671 B/op 10707 allocs/op
BenchmarkRepeated/input_size_5000-8 448 2468527 ns/op 178.24 MB/s 1514684 B/op 10708 allocs/op
BenchmarkRepeated/input_size_5000-8 448 2489199 ns/op 176.76 MB/s 1514738 B/op 10709 allocs/op
BenchmarkRepeated/input_size_5000-8 446 2492202 ns/op 176.55 MB/s 1514692 B/op 10708 allocs/op
BenchmarkRepeated/input_size_5000-8 462 2480510 ns/op 177.38 MB/s 1514608 B/op 10707 allocs/op
BenchmarkRepeated/input_size_10000
BenchmarkRepeated/input_size_10000-8 235 4723582 ns/op 186.30 MB/s 2868784 B/op 20753 allocs/op
BenchmarkRepeated/input_size_10000-8 243 4733827 ns/op 185.90 MB/s 2868906 B/op 20754 allocs/op
BenchmarkRepeated/input_size_10000-8 246 4753046 ns/op 185.14 MB/s 2868742 B/op 20753 allocs/op
BenchmarkRepeated/input_size_10000-8 237 4876943 ns/op 180.44 MB/s 2868895 B/op 20754 allocs/op
BenchmarkRepeated/input_size_10000-8 238 4689277 ns/op 187.66 MB/s 2868837 B/op 20753 allocs/op
BenchmarkRepeated/input_size_10000-8 237 4768075 ns/op 184.56 MB/s 2868856 B/op 20754 allocs/op
BenchmarkRepeated/input_size_10000-8 235 4754508 ns/op 185.09 MB/s 2868845 B/op 20754 allocs/op
BenchmarkRepeated/input_size_10000-8 238 4783239 ns/op 183.98 MB/s 2868790 B/op 20753 allocs/op
BenchmarkRepeated/input_size_10000-8 246 4789796 ns/op 183.72 MB/s 2868815 B/op 20753 allocs/op
BenchmarkRepeated/input_size_10000-8 236 4778784 ns/op 184.15 MB/s 2868715 B/op 20750 allocs/op
BenchmarkRepeated/input_size_20000
BenchmarkRepeated/input_size_20000-8 120 9157366 ns/op 192.20 MB/s 5584130 B/op 40812 allocs/op
BenchmarkRepeated/input_size_20000-8 127 9129399 ns/op 192.78 MB/s 5584252 B/op 40810 allocs/op
BenchmarkRepeated/input_size_20000-8 118 9052981 ns/op 194.41 MB/s 5584291 B/op 40816 allocs/op
BenchmarkRepeated/input_size_20000-8 123 9051090 ns/op 194.45 MB/s 5584023 B/op 40810 allocs/op
BenchmarkRepeated/input_size_20000-8 122 9295392 ns/op 189.34 MB/s 5584148 B/op 40810 allocs/op
BenchmarkRepeated/input_size_20000-8 122 9185556 ns/op 191.61 MB/s 5584088 B/op 40814 allocs/op
BenchmarkRepeated/input_size_20000-8 120 9186201 ns/op 191.59 MB/s 5584291 B/op 40815 allocs/op
BenchmarkRepeated/input_size_20000-8 124 9201804 ns/op 191.27 MB/s 5584417 B/op 40822 allocs/op
BenchmarkRepeated/input_size_20000-8 124 9085248 ns/op 193.72 MB/s 5584195 B/op 40815 allocs/op
BenchmarkRepeated/input_size_20000-8 123 9100675 ns/op 193.39 MB/s 5584316 B/op 40815 allocs/op
PASS
ok github.com/CaduceusMetaverseProtocol/MetaProtocol/benchmark 117.943s
goos: linux
goarch: amd64
pkg: github.com/CaduceusMetaverseProtocol/MetaProtocol/benchmark
cpu: Intel(R) Xeon(R) Platinum 8275CL CPU @ 3.00GHz
BenchmarkRepeated
BenchmarkRepeated/input_size_100
BenchmarkRepeated/input_size_100-8 5110 222753 ns/op 60.83 MB/s 4489 tps 253842 B/op 2123 allocs/op
BenchmarkRepeated/input_size_100-8 5496 217537 ns/op 62.28 MB/s 4597 tps 253631 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5122 219980 ns/op 61.59 MB/s 4546 tps 253506 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5452 208001 ns/op 65.14 MB/s 4808 tps 253509 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5037 214631 ns/op 63.13 MB/s 4659 tps 253551 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5090 217929 ns/op 62.17 MB/s 4589 tps 253608 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5116 215237 ns/op 62.95 MB/s 4646 tps 253592 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5113 213546 ns/op 63.45 MB/s 4683 tps 253605 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5022 215134 ns/op 62.98 MB/s 4648 tps 253591 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5062 218706 ns/op 61.95 MB/s 4572 tps 253611 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5104 213766 ns/op 63.38 MB/s 4678 tps 253600 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5032 215032 ns/op 63.01 MB/s 4650 tps 253604 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5049 207689 ns/op 65.24 MB/s 4815 tps 253601 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5341 210830 ns/op 64.27 MB/s 4743 tps 253608 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5660 214010 ns/op 63.31 MB/s 4673 tps 253630 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 4976 212463 ns/op 63.77 MB/s 4707 tps 253602 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5080 207759 ns/op 65.22 MB/s 4813 tps 253608 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5138 212662 ns/op 63.71 MB/s 4702 tps 253597 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5060 221682 ns/op 61.12 MB/s 4511 tps 253610 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5145 210412 ns/op 64.39 MB/s 4752 tps 253593 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 4976 210343 ns/op 64.41 MB/s 4754 tps 253607 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5334 210894 ns/op 64.25 MB/s 4742 tps 253599 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 4966 224630 ns/op 60.32 MB/s 4452 tps 253598 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5625 210153 ns/op 64.47 MB/s 4758 tps 253598 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5019 217155 ns/op 62.39 MB/s 4605 tps 253593 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5022 208464 ns/op 64.99 MB/s 4797 tps 253600 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5025 212852 ns/op 63.65 MB/s 4698 tps 253605 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 4917 205715 ns/op 65.86 MB/s 4861 tps 253605 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 4743 217717 ns/op 62.23 MB/s 4593 tps 253608 B/op 2122 allocs/op
BenchmarkRepeated/input_size_100-8 5089 211758 ns/op 63.98 MB/s 4722 tps 253595 B/op 2122 allocs/op
BenchmarkRepeated/input_size_200
BenchmarkRepeated/input_size_200-8 3661 291288 ns/op 92.87 MB/s 3433 tps 365228 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3757 274628 ns/op 98.50 MB/s 3641 tps 365227 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 4240 285654 ns/op 94.70 MB/s 3501 tps 365237 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3757 277146 ns/op 97.61 MB/s 3608 tps 365237 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3609 277745 ns/op 97.40 MB/s 3600 tps 365235 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3782 285897 ns/op 94.62 MB/s 3498 tps 365244 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3800 283183 ns/op 95.52 MB/s 3531 tps 365231 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3739 279661 ns/op 96.73 MB/s 3576 tps 365239 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3621 282386 ns/op 95.79 MB/s 3541 tps 365238 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 4264 277323 ns/op 97.54 MB/s 3606 tps 365229 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3804 281604 ns/op 96.06 MB/s 3551 tps 365235 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 4192 288112 ns/op 93.89 MB/s 3471 tps 365239 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3660 276930 ns/op 97.68 MB/s 3611 tps 365245 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3703 290221 ns/op 93.21 MB/s 3446 tps 365210 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3823 286055 ns/op 94.57 MB/s 3495 tps 365240 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3698 282000 ns/op 95.93 MB/s 3546 tps 365230 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3715 290177 ns/op 93.22 MB/s 3446 tps 365242 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3645 285571 ns/op 94.73 MB/s 3502 tps 365236 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3576 284478 ns/op 95.09 MB/s 3515 tps 365184 B/op 3622 allocs/op
BenchmarkRepeated/input_size_200-8 3832 289394 ns/op 93.47 MB/s 3455 tps 365237 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3682 295154 ns/op 91.65 MB/s 3388 tps 365241 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3595 281789 ns/op 96.00 MB/s 3549 tps 365245 B/op 3624 allocs/op
BenchmarkRepeated/input_size_200-8 4268 284084 ns/op 95.22 MB/s 3520 tps 365237 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3792 288551 ns/op 93.75 MB/s 3466 tps 365239 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3825 286659 ns/op 94.37 MB/s 3488 tps 365230 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3650 284540 ns/op 95.07 MB/s 3514 tps 365232 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3720 284502 ns/op 95.08 MB/s 3515 tps 365220 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3636 289834 ns/op 93.33 MB/s 3450 tps 365242 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3624 302089 ns/op 89.55 MB/s 3310 tps 365231 B/op 3623 allocs/op
BenchmarkRepeated/input_size_200-8 3693 278152 ns/op 97.25 MB/s 3595 tps 365229 B/op 3623 allocs/op
BenchmarkRepeated/input_size_500
BenchmarkRepeated/input_size_500-8 2110 517539 ns/op 130.52 MB/s 1932 tps 701703 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2088 539764 ns/op 125.15 MB/s 1853 tps 701721 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2229 529916 ns/op 127.48 MB/s 1887 tps 701695 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2186 522612 ns/op 129.26 MB/s 1913 tps 701710 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2067 539120 ns/op 125.30 MB/s 1855 tps 701712 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2166 523016 ns/op 129.16 MB/s 1912 tps 701688 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2100 529922 ns/op 127.47 MB/s 1887 tps 701700 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2139 524351 ns/op 128.83 MB/s 1907 tps 701712 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2274 517572 ns/op 130.52 MB/s 1932 tps 701689 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2190 522594 ns/op 129.26 MB/s 1914 tps 701712 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2253 542528 ns/op 124.51 MB/s 1843 tps 701699 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2066 522579 ns/op 129.26 MB/s 1914 tps 701802 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 1996 519239 ns/op 130.10 MB/s 1926 tps 701818 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2088 528394 ns/op 127.84 MB/s 1893 tps 701818 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2080 518343 ns/op 130.32 MB/s 1929 tps 701834 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2180 524944 ns/op 128.68 MB/s 1905 tps 701825 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2068 519851 ns/op 129.94 MB/s 1924 tps 701817 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2140 528782 ns/op 127.75 MB/s 1891 tps 701803 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2143 522106 ns/op 129.38 MB/s 1915 tps 701823 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2095 512802 ns/op 131.73 MB/s 1950 tps 701818 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2113 515133 ns/op 131.13 MB/s 1941 tps 701824 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2155 523176 ns/op 129.12 MB/s 1911 tps 701815 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2304 511305 ns/op 132.12 MB/s 1956 tps 701811 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2142 516772 ns/op 130.72 MB/s 1935 tps 701828 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2097 514570 ns/op 131.28 MB/s 1943 tps 701805 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2143 528002 ns/op 127.94 MB/s 1894 tps 701823 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2223 519637 ns/op 130.00 MB/s 1924 tps 701823 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2095 524635 ns/op 128.76 MB/s 1906 tps 701827 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 2078 519893 ns/op 129.93 MB/s 1923 tps 701823 B/op 8144 allocs/op
BenchmarkRepeated/input_size_500-8 1890 535375 ns/op 126.18 MB/s 1868 tps 701826 B/op 8144 allocs/op
BenchmarkRepeated/input_size_1000
BenchmarkRepeated/input_size_1000-8 1340 896408 ns/op 150.66 MB/s 1116 tps 1226627 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 1101 924146 ns/op 146.14 MB/s 1082 tps 1226666 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 1288 893443 ns/op 151.16 MB/s 1119 tps 1226655 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 1197 907642 ns/op 148.79 MB/s 1102 tps 1226664 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 1318 905217 ns/op 149.19 MB/s 1105 tps 1226616 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 1234 1041747 ns/op 129.64 MB/s 959.9 tps 1226641 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 945 1059859 ns/op 127.42 MB/s 943.5 tps 1226623 B/op 15645 allocs/op
BenchmarkRepeated/input_size_1000-8 1136 1040900 ns/op 129.74 MB/s 960.7 tps 1226633 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 1051 1036769 ns/op 130.26 MB/s 964.5 tps 1226669 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 1136 1034395 ns/op 130.56 MB/s 966.7 tps 1226646 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 969 1044882 ns/op 129.25 MB/s 957.0 tps 1226648 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 1012 1056285 ns/op 127.85 MB/s 946.7 tps 1226682 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 1189 1048434 ns/op 128.81 MB/s 953.8 tps 1226640 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 1166 1032403 ns/op 130.81 MB/s 968.6 tps 1226669 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 1059 1052313 ns/op 128.34 MB/s 950.3 tps 1226687 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 1029 1064225 ns/op 126.90 MB/s 939.6 tps 1226668 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 1149 1027182 ns/op 131.48 MB/s 973.5 tps 1226623 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 1154 1002640 ns/op 134.70 MB/s 997.4 tps 1226639 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 1035 1050391 ns/op 128.57 MB/s 952.0 tps 1226665 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 979 1037538 ns/op 130.16 MB/s 963.8 tps 1226668 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 1130 1016761 ns/op 132.82 MB/s 983.5 tps 1226624 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 1159 1036076 ns/op 130.35 MB/s 965.2 tps 1226646 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 1228 1023551 ns/op 131.94 MB/s 977.0 tps 1226661 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 1020 1042597 ns/op 129.53 MB/s 959.1 tps 1226685 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 1042 1048164 ns/op 128.85 MB/s 954.0 tps 1226653 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 1156 1059050 ns/op 127.52 MB/s 944.2 tps 1226636 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 1027 1033617 ns/op 130.66 MB/s 967.5 tps 1226682 B/op 15647 allocs/op
BenchmarkRepeated/input_size_1000-8 1050 1037713 ns/op 130.14 MB/s 963.6 tps 1226673 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 1009 1027104 ns/op 131.49 MB/s 973.6 tps 1226611 B/op 15646 allocs/op
BenchmarkRepeated/input_size_1000-8 944 1098091 ns/op 122.99 MB/s 910.7 tps 1226643 B/op 15646 allocs/op
BenchmarkRepeated/input_size_2000
BenchmarkRepeated/input_size_2000-8 595 1956067 ns/op 138.06 MB/s 511.2 tps 2276756 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 591 1971791 ns/op 136.96 MB/s 507.1 tps 2276803 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 535 1972806 ns/op 136.89 MB/s 506.9 tps 2276788 B/op 30668 allocs/op
BenchmarkRepeated/input_size_2000-8 549 1958959 ns/op 137.85 MB/s 510.5 tps 2276793 B/op 30668 allocs/op
BenchmarkRepeated/input_size_2000-8 547 1963388 ns/op 137.54 MB/s 509.3 tps 2276803 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 537 1942837 ns/op 139.00 MB/s 514.7 tps 2276773 B/op 30668 allocs/op
BenchmarkRepeated/input_size_2000-8 556 1944617 ns/op 138.87 MB/s 514.2 tps 2276772 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 558 1949578 ns/op 138.52 MB/s 512.9 tps 2276862 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 572 1934702 ns/op 139.58 MB/s 516.9 tps 2276792 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 570 1961559 ns/op 137.67 MB/s 509.8 tps 2276781 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 554 1967470 ns/op 137.26 MB/s 508.2 tps 2276812 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 553 1920529 ns/op 140.61 MB/s 520.7 tps 2276774 B/op 30668 allocs/op
BenchmarkRepeated/input_size_2000-8 574 1900779 ns/op 142.07 MB/s 526.1 tps 2276797 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 534 1943045 ns/op 138.98 MB/s 514.6 tps 2276758 B/op 30668 allocs/op
BenchmarkRepeated/input_size_2000-8 552 1956827 ns/op 138.00 MB/s 511.0 tps 2276825 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 614 1987193 ns/op 135.90 MB/s 503.2 tps 2276764 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 561 1939184 ns/op 139.26 MB/s 515.7 tps 2276822 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 534 1911620 ns/op 141.27 MB/s 523.1 tps 2276748 B/op 30668 allocs/op
BenchmarkRepeated/input_size_2000-8 528 1951684 ns/op 138.37 MB/s 512.4 tps 2276752 B/op 30668 allocs/op
BenchmarkRepeated/input_size_2000-8 542 1938784 ns/op 139.29 MB/s 515.8 tps 2276849 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 565 1944449 ns/op 138.88 MB/s 514.3 tps 2276729 B/op 30667 allocs/op
BenchmarkRepeated/input_size_2000-8 562 1923476 ns/op 140.40 MB/s 519.9 tps 2276755 B/op 30668 allocs/op
BenchmarkRepeated/input_size_2000-8 555 1968212 ns/op 137.21 MB/s 508.1 tps 2276862 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 564 1925232 ns/op 140.27 MB/s 519.4 tps 2276785 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 558 1920005 ns/op 140.65 MB/s 520.8 tps 2276744 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 535 1922998 ns/op 140.43 MB/s 520.0 tps 2276787 B/op 30668 allocs/op
BenchmarkRepeated/input_size_2000-8 541 1942631 ns/op 139.01 MB/s 514.8 tps 2276820 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 532 1961415 ns/op 137.68 MB/s 509.8 tps 2276854 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 554 1945026 ns/op 138.84 MB/s 514.1 tps 2276839 B/op 30669 allocs/op
BenchmarkRepeated/input_size_2000-8 525 1929464 ns/op 139.96 MB/s 518.3 tps 2276782 B/op 30668 allocs/op
BenchmarkRepeated/input_size_5000
BenchmarkRepeated/input_size_5000-8 250 4594438 ns/op 146.93 MB/s 217.7 tps 5475880 B/op 75712 allocs/op
BenchmarkRepeated/input_size_5000-8 241 4671504 ns/op 144.50 MB/s 214.1 tps 5476090 B/op 75713 allocs/op
BenchmarkRepeated/input_size_5000-8 242 4492143 ns/op 150.27 MB/s 222.6 tps 5475955 B/op 75712 allocs/op
BenchmarkRepeated/input_size_5000-8 241 4627532 ns/op 145.88 MB/s 216.1 tps 5476081 B/op 75713 allocs/op
BenchmarkRepeated/input_size_5000-8 238 4553809 ns/op 148.24 MB/s 219.6 tps 5476061 B/op 75714 allocs/op
BenchmarkRepeated/input_size_5000-8 243 4588073 ns/op 147.13 MB/s 218.0 tps 5476086 B/op 75714 allocs/op
BenchmarkRepeated/input_size_5000-8 246 4523418 ns/op 149.23 MB/s 221.1 tps 5476044 B/op 75714 allocs/op
BenchmarkRepeated/input_size_5000-8 248 4504832 ns/op 149.85 MB/s 222.0 tps 5476049 B/op 75712 allocs/op
BenchmarkRepeated/input_size_5000-8 250 4562534 ns/op 147.96 MB/s 219.2 tps 5476086 B/op 75714 allocs/op
BenchmarkRepeated/input_size_5000-8 243 4593308 ns/op 146.96 MB/s 217.7 tps 5476006 B/op 75712 allocs/op
BenchmarkRepeated/input_size_5000-8 246 4653727 ns/op 145.06 MB/s 214.9 tps 5476048 B/op 75713 allocs/op
BenchmarkRepeated/input_size_5000-8 258 4586677 ns/op 147.18 MB/s 218.0 tps 5475968 B/op 75713 allocs/op
BenchmarkRepeated/input_size_5000-8 252 4541888 ns/op 148.63 MB/s 220.2 tps 5476089 B/op 75714 allocs/op
BenchmarkRepeated/input_size_5000-8 246 4606279 ns/op 146.55 MB/s 217.1 tps 5475822 B/op 75711 allocs/op
BenchmarkRepeated/input_size_5000-8 240 4749099 ns/op 142.14 MB/s 210.6 tps 5476256 B/op 75715 allocs/op
BenchmarkRepeated/input_size_5000-8 252 4576978 ns/op 147.49 MB/s 218.5 tps 5476037 B/op 75714 allocs/op
BenchmarkRepeated/input_size_5000-8 248 4596578 ns/op 146.86 MB/s 217.5 tps 5476077 B/op 75713 allocs/op
BenchmarkRepeated/input_size_5000-8 252 4581860 ns/op 147.33 MB/s 218.2 tps 5475988 B/op 75713 allocs/op
BenchmarkRepeated/input_size_5000-8 244 4586904 ns/op 147.17 MB/s 218.0 tps 5476082 B/op 75714 allocs/op
BenchmarkRepeated/input_size_5000-8 256 4569787 ns/op 147.72 MB/s 218.8 tps 5476031 B/op 75713 allocs/op
BenchmarkRepeated/input_size_5000-8 250 4469578 ns/op 151.03 MB/s 223.7 tps 5476005 B/op 75714 allocs/op
BenchmarkRepeated/input_size_5000-8 247 4614240 ns/op 146.30 MB/s 216.7 tps 5476186 B/op 75715 allocs/op
BenchmarkRepeated/input_size_5000-8 242 4694316 ns/op 143.80 MB/s 213.0 tps 5476003 B/op 75713 allocs/op
BenchmarkRepeated/input_size_5000-8 252 4598824 ns/op 146.79 MB/s 217.4 tps 5475943 B/op 75712 allocs/op
BenchmarkRepeated/input_size_5000-8 241 4566682 ns/op 147.82 MB/s 219.0 tps 5475978 B/op 75714 allocs/op
BenchmarkRepeated/input_size_5000-8 248 4589996 ns/op 147.07 MB/s 217.9 tps 5476061 B/op 75713 allocs/op
BenchmarkRepeated/input_size_5000-8 248 4717519 ns/op 143.09 MB/s 212.0 tps 5476113 B/op 75714 allocs/op
BenchmarkRepeated/input_size_5000-8 246 4792403 ns/op 140.86 MB/s 208.6 tps 5476230 B/op 75714 allocs/op
BenchmarkRepeated/input_size_5000-8 244 4623373 ns/op 146.01 MB/s 216.3 tps 5475961 B/op 75713 allocs/op
BenchmarkRepeated/input_size_5000-8 256 4537364 ns/op 148.78 MB/s 220.4 tps 5476020 B/op 75713 allocs/op
BenchmarkRepeated/input_size_10000
BenchmarkRepeated/input_size_10000-8 127 8750303 ns/op 154.29 MB/s 114.3 tps 10773777 B/op 150760 allocs/op
BenchmarkRepeated/input_size_10000-8 128 8851712 ns/op 152.52 MB/s 113.0 tps 10773919 B/op 150760 allocs/op
BenchmarkRepeated/input_size_10000-8 129 8871950 ns/op 152.17 MB/s 112.7 tps 10774094 B/op 150762 allocs/op
BenchmarkRepeated/input_size_10000-8 129 8855240 ns/op 152.46 MB/s 112.9 tps 10773950 B/op 150759 allocs/op
BenchmarkRepeated/input_size_10000-8 130 8949288 ns/op 150.86 MB/s 111.7 tps 10773949 B/op 150762 allocs/op
BenchmarkRepeated/input_size_10000-8 127 8954324 ns/op 150.77 MB/s 111.7 tps 10773628 B/op 150759 allocs/op
BenchmarkRepeated/input_size_10000-8 124 8824311 ns/op 152.99 MB/s 113.3 tps 10773858 B/op 150756 allocs/op
BenchmarkRepeated/input_size_10000-8 128 8926795 ns/op 151.24 MB/s 112.0 tps 10773905 B/op 150760 allocs/op
BenchmarkRepeated/input_size_10000-8 126 8883701 ns/op 151.97 MB/s 112.6 tps 10773726 B/op 150757 allocs/op
BenchmarkRepeated/input_size_10000-8 133 8914630 ns/op 151.44 MB/s 112.2 tps 10773809 B/op 150760 allocs/op
BenchmarkRepeated/input_size_10000-8 127 8796395 ns/op 153.48 MB/s 113.7 tps 10773946 B/op 150761 allocs/op
BenchmarkRepeated/input_size_10000-8 126 8916102 ns/op 151.42 MB/s 112.2 tps 10773868 B/op 150761 allocs/op
BenchmarkRepeated/input_size_10000-8 126 8800739 ns/op 153.40 MB/s 113.6 tps 10773681 B/op 150758 allocs/op
BenchmarkRepeated/input_size_10000-8 132 8755424 ns/op 154.20 MB/s 114.2 tps 10773968 B/op 150762 allocs/op
BenchmarkRepeated/input_size_10000-8 129 8653334 ns/op 156.02 MB/s 115.6 tps 10773927 B/op 150763 allocs/op
BenchmarkRepeated/input_size_10000-8 130 8833729 ns/op 152.83 MB/s 113.2 tps 10773690 B/op 150759 allocs/op
BenchmarkRepeated/input_size_10000-8 134 8780494 ns/op 153.76 MB/s 113.9 tps 10773768 B/op 150759 allocs/op
BenchmarkRepeated/input_size_10000-8 126 8835595 ns/op 152.80 MB/s 113.2 tps 10773908 B/op 150757 allocs/op
BenchmarkRepeated/input_size_10000-8 128 8919290 ns/op 151.36 MB/s 112.1 tps 10773815 B/op 150758 allocs/op
BenchmarkRepeated/input_size_10000-8 127 9030739 ns/op 149.50 MB/s 110.7 tps 10773874 B/op 150760 allocs/op
BenchmarkRepeated/input_size_10000-8 121 9088411 ns/op 148.55 MB/s 110.0 tps 10774091 B/op 150765 allocs/op
BenchmarkRepeated/input_size_10000-8 130 8719550 ns/op 154.83 MB/s 114.7 tps 10773837 B/op 150758 allocs/op
BenchmarkRepeated/input_size_10000-8 128 8892093 ns/op 151.83 MB/s 112.5 tps 10773883 B/op 150762 allocs/op
BenchmarkRepeated/input_size_10000-8 133 8995606 ns/op 150.08 MB/s 111.2 tps 10773832 B/op 150762 allocs/op
BenchmarkRepeated/input_size_10000-8 129 8785753 ns/op 153.66 MB/s 113.8 tps 10773718 B/op 150759 allocs/op
BenchmarkRepeated/input_size_10000-8 130 8924614 ns/op 151.27 MB/s 112.0 tps 10773848 B/op 150761 allocs/op
BenchmarkRepeated/input_size_10000-8 128 8878845 ns/op 152.05 MB/s 112.6 tps 10773796 B/op 150760 allocs/op
BenchmarkRepeated/input_size_10000-8 130 8650580 ns/op 156.06 MB/s 115.6 tps 10773766 B/op 150759 allocs/op
BenchmarkRepeated/input_size_10000-8 132 8748450 ns/op 154.32 MB/s 114.3 tps 10773672 B/op 150756 allocs/op
BenchmarkRepeated/input_size_10000-8 132 8875261 ns/op 152.11 MB/s 112.7 tps 10774170 B/op 150765 allocs/op
BenchmarkRepeated/input_size_20000
BenchmarkRepeated/input_size_20000-8 61 17215587 ns/op 156.84 MB/s 58.09 tps 21391717 B/op 300808 allocs/op
BenchmarkRepeated/input_size_20000-8 67 17031374 ns/op 158.53 MB/s 58.71 tps 21392049 B/op 300820 allocs/op
BenchmarkRepeated/input_size_20000-8 67 16725842 ns/op 161.43 MB/s 59.78 tps 21391618 B/op 300812 allocs/op
BenchmarkRepeated/input_size_20000-8 64 17243531 ns/op 156.58 MB/s 57.99 tps 21392230 B/op 300824 allocs/op
BenchmarkRepeated/input_size_20000-8 66 17079561 ns/op 158.09 MB/s 58.55 tps 21392217 B/op 300821 allocs/op
BenchmarkRepeated/input_size_20000-8 69 16565850 ns/op 162.99 MB/s 60.36 tps 21392102 B/op 300817 allocs/op
BenchmarkRepeated/input_size_20000-8 64 17038167 ns/op 158.47 MB/s 58.69 tps 21392273 B/op 300821 allocs/op
BenchmarkRepeated/input_size_20000-8 68 16626401 ns/op 162.40 MB/s 60.14 tps 21392465 B/op 300828 allocs/op
BenchmarkRepeated/input_size_20000-8 68 16926315 ns/op 159.52 MB/s 59.08 tps 21392502 B/op 300827 allocs/op
BenchmarkRepeated/input_size_20000-8 69 16923952 ns/op 159.54 MB/s 59.09 tps 21392568 B/op 300820 allocs/op
BenchmarkRepeated/input_size_20000-8 66 16992988 ns/op 158.89 MB/s 58.85 tps 21391922 B/op 300816 allocs/op
BenchmarkRepeated/input_size_20000-8 63 16692143 ns/op 161.76 MB/s 59.91 tps 21392192 B/op 300822 allocs/op
BenchmarkRepeated/input_size_20000-8 66 16808042 ns/op 160.64 MB/s 59.49 tps 21392230 B/op 300826 allocs/op
BenchmarkRepeated/input_size_20000-8 64 16919021 ns/op 159.59 MB/s 59.10 tps 21392101 B/op 300818 allocs/op
BenchmarkRepeated/input_size_20000-8 66 16600777 ns/op 162.65 MB/s 60.23 tps 21391979 B/op 300822 allocs/op
BenchmarkRepeated/input_size_20000-8 67 16958133 ns/op 159.22 MB/s 58.97 tps 21392377 B/op 300823 allocs/op
BenchmarkRepeated/input_size_20000-8 64 17119208 ns/op 157.72 MB/s 58.41 tps 21392259 B/op 300815 allocs/op
BenchmarkRepeated/input_size_20000-8 69 17120921 ns/op 157.70 MB/s 58.40 tps 21392166 B/op 300822 allocs/op
BenchmarkRepeated/input_size_20000-8 70 17179414 ns/op 157.17 MB/s 58.21 tps 21392363 B/op 300820 allocs/op
BenchmarkRepeated/input_size_20000-8 67 16906712 ns/op 159.70 MB/s 59.15 tps 21392247 B/op 300824 allocs/op
BenchmarkRepeated/input_size_20000-8 64 16855940 ns/op 160.18 MB/s 59.32 tps 21392231 B/op 300820 allocs/op
BenchmarkRepeated/input_size_20000-8 70 16792442 ns/op 160.79 MB/s 59.55 tps 21392453 B/op 300823 allocs/op
BenchmarkRepeated/input_size_20000-8 64 17029458 ns/op 158.55 MB/s 58.72 tps 21392301 B/op 300824 allocs/op
BenchmarkRepeated/input_size_20000-8 67 17271288 ns/op 156.33 MB/s 57.90 tps 21392157 B/op 300818 allocs/op
BenchmarkRepeated/input_size_20000-8 68 17355446 ns/op 155.57 MB/s 57.62 tps 21392984 B/op 300827 allocs/op
BenchmarkRepeated/input_size_20000-8 62 17065754 ns/op 158.21 MB/s 58.60 tps 21392602 B/op 300829 allocs/op
BenchmarkRepeated/input_size_20000-8 66 16637103 ns/op 162.29 MB/s 60.11 tps 21392432 B/op 300824 allocs/op
BenchmarkRepeated/input_size_20000-8 67 17284400 ns/op 156.21 MB/s 57.85 tps 21392374 B/op 300823 allocs/op
BenchmarkRepeated/input_size_20000-8 67 17015613 ns/op 158.68 MB/s 58.77 tps 21392602 B/op 300827 allocs/op
BenchmarkRepeated/input_size_20000-8 66 16573354 ns/op 162.92 MB/s 60.34 tps 21392218 B/op 300823 allocs/op
PASS
ok github.com/CaduceusMetaverseProtocol/MetaProtocol/benchmark 345.885s
goos: linux
goarch: amd64
pkg: github.com/CaduceusMetaverseProtocol/MetaProtocol/benchmark
cpu: Intel(R) Xeon(R) Platinum 8275CL CPU @ 3.00GHz
BenchmarkRepeated
BenchmarkRepeated/input_size_100
BenchmarkRepeated/input_size_100-8 5694 203058 ns/op 43.34 MB/s 188406 B/op 830 allocs/op
BenchmarkRepeated/input_size_100-8 6213 193237 ns/op 45.54 MB/s 188209 B/op 830 allocs/op
BenchmarkRepeated/input_size_100-8 6325 195312 ns/op 45.06 MB/s 188155 B/op 830 allocs/op
BenchmarkRepeated/input_size_100-8 5516 189930 ns/op 46.33 MB/s 188207 B/op 830 allocs/op
BenchmarkRepeated/input_size_100-8 6348 188265 ns/op 46.74 MB/s 188204 B/op 830 allocs/op
BenchmarkRepeated/input_size_100-8 5312 189058 ns/op 46.55 MB/s 188197 B/op 830 allocs/op
BenchmarkRepeated/input_size_100-8 5334 187518 ns/op 46.93 MB/s 188204 B/op 830 allocs/op
BenchmarkRepeated/input_size_100-8 5552 187125 ns/op 47.03 MB/s 188205 B/op 830 allocs/op
BenchmarkRepeated/input_size_100-8 5472 189904 ns/op 46.34 MB/s 188201 B/op 830 allocs/op
BenchmarkRepeated/input_size_100-8 5398 187404 ns/op 46.96 MB/s 188194 B/op 830 allocs/op
BenchmarkRepeated/input_size_200
BenchmarkRepeated/input_size_200-8 4590 239832 ns/op 73.38 MB/s 234140 B/op 1031 allocs/op
BenchmarkRepeated/input_size_200-8 4516 246288 ns/op 71.46 MB/s 234143 B/op 1031 allocs/op
BenchmarkRepeated/input_size_200-8 4681 235289 ns/op 74.80 MB/s 234137 B/op 1031 allocs/op
BenchmarkRepeated/input_size_200-8 4447 247292 ns/op 71.17 MB/s 234137 B/op 1031 allocs/op
BenchmarkRepeated/input_size_200-8 4593 241079 ns/op 73.01 MB/s 234136 B/op 1031 allocs/op
BenchmarkRepeated/input_size_200-8 4513 241271 ns/op 72.95 MB/s 234140 B/op 1031 allocs/op
BenchmarkRepeated/input_size_200-8 4804 239761 ns/op 73.41 MB/s 234140 B/op 1031 allocs/op
BenchmarkRepeated/input_size_200-8 4544 237895 ns/op 73.98 MB/s 234125 B/op 1031 allocs/op
BenchmarkRepeated/input_size_200-8 4396 239111 ns/op 73.61 MB/s 234133 B/op 1031 allocs/op
BenchmarkRepeated/input_size_200-8 4520 241667 ns/op 72.83 MB/s 234144 B/op 1031 allocs/op
BenchmarkRepeated/input_size_500
BenchmarkRepeated/input_size_500-8 2887 402188 ns/op 109.40 MB/s 368042 B/op 1650 allocs/op
BenchmarkRepeated/input_size_500-8 3027 401929 ns/op 109.47 MB/s 368052 B/op 1650 allocs/op
BenchmarkRepeated/input_size_500-8 2859 394197 ns/op 111.62 MB/s 368047 B/op 1650 allocs/op
BenchmarkRepeated/input_size_500-8 2811 405032 ns/op 108.63 MB/s 368049 B/op 1650 allocs/op
BenchmarkRepeated/input_size_500-8 2886 414027 ns/op 106.27 MB/s 368049 B/op 1650 allocs/op
BenchmarkRepeated/input_size_500-8 2953 406307 ns/op 108.29 MB/s 368051 B/op 1650 allocs/op
BenchmarkRepeated/input_size_500-8 2836 391173 ns/op 112.48 MB/s 368054 B/op 1650 allocs/op
BenchmarkRepeated/input_size_500-8 2859 413669 ns/op 106.37 MB/s 368053 B/op 1650 allocs/op
BenchmarkRepeated/input_size_500-8 3042 398651 ns/op 110.37 MB/s 368061 B/op 1650 allocs/op
BenchmarkRepeated/input_size_500-8 2828 402082 ns/op 109.43 MB/s 368044 B/op 1650 allocs/op
BenchmarkRepeated/input_size_1000
BenchmarkRepeated/input_size_1000-8 1700 654912 ns/op 134.37 MB/s 567251 B/op 2651 allocs/op
BenchmarkRepeated/input_size_1000-8 1791 653851 ns/op 134.59 MB/s 567233 B/op 2651 allocs/op
BenchmarkRepeated/input_size_1000-8 1794 644854 ns/op 136.47 MB/s 567234 B/op 2651 allocs/op
BenchmarkRepeated/input_size_1000-8 1668 661167 ns/op 133.10 MB/s 567256 B/op 2651 allocs/op
BenchmarkRepeated/input_size_1000-8 1597 662501 ns/op 132.83 MB/s 567260 B/op 2651 allocs/op
BenchmarkRepeated/input_size_1000-8 1549 662552 ns/op 132.82 MB/s 567229 B/op 2651 allocs/op
BenchmarkRepeated/input_size_1000-8 1688 655490 ns/op 134.25 MB/s 567268 B/op 2652 allocs/op
BenchmarkRepeated/input_size_1000-8 1514 667790 ns/op 131.78 MB/s 567271 B/op 2652 allocs/op
BenchmarkRepeated/input_size_1000-8 1975 663148 ns/op 132.70 MB/s 567260 B/op 2652 allocs/op
BenchmarkRepeated/input_size_1000-8 1899 648360 ns/op 135.73 MB/s 567231 B/op 2651 allocs/op
BenchmarkRepeated/input_size_2000
BenchmarkRepeated/input_size_2000-8 954 1154544 ns/op 152.44 MB/s 966011 B/op 4671 allocs/op
BenchmarkRepeated/input_size_2000-8 902 1148037 ns/op 153.31 MB/s 966041 B/op 4672 allocs/op
BenchmarkRepeated/input_size_2000-8 1022 1147506 ns/op 153.38 MB/s 966051 B/op 4672 allocs/op
BenchmarkRepeated/input_size_2000-8 883 1165710 ns/op 150.98 MB/s 966048 B/op 4672 allocs/op
BenchmarkRepeated/input_size_2000-8 909 1165233 ns/op 151.04 MB/s 966076 B/op 4672 allocs/op
BenchmarkRepeated/input_size_2000-8 963 1162700 ns/op 151.37 MB/s 966022 B/op 4671 allocs/op
BenchmarkRepeated/input_size_2000-8 1024 1145474 ns/op 153.65 MB/s 966001 B/op 4671 allocs/op
BenchmarkRepeated/input_size_2000-8 937 1161682 ns/op 151.50 MB/s 966028 B/op 4671 allocs/op
BenchmarkRepeated/input_size_2000-8 993 1155197 ns/op 152.36 MB/s 965980 B/op 4671 allocs/op
BenchmarkRepeated/input_size_2000-8 946 1171051 ns/op 150.29 MB/s 966057 B/op 4672 allocs/op
BenchmarkRepeated/input_size_5000
BenchmarkRepeated/input_size_5000-8 406 2656873 ns/op 165.61 MB/s 2195011 B/op 10711 allocs/op
BenchmarkRepeated/input_size_5000-8 400 2704418 ns/op 162.70 MB/s 2195024 B/op 10711 allocs/op
BenchmarkRepeated/input_size_5000-8 392 2671657 ns/op 164.69 MB/s 2195052 B/op 10711 allocs/op
BenchmarkRepeated/input_size_5000-8 410 2622865 ns/op 167.76 MB/s 2194980 B/op 10711 allocs/op
BenchmarkRepeated/input_size_5000-8 416 2665583 ns/op 165.07 MB/s 2195057 B/op 10712 allocs/op
BenchmarkRepeated/input_size_5000-8 391 2978365 ns/op 147.73 MB/s 2195137 B/op 10714 allocs/op
BenchmarkRepeated/input_size_5000-8 444 2655882 ns/op 165.67 MB/s 2195002 B/op 10712 allocs/op
BenchmarkRepeated/input_size_5000-8 415 2739235 ns/op 160.63 MB/s 2195053 B/op 10712 allocs/op
BenchmarkRepeated/input_size_5000-8 398 2716725 ns/op 161.96 MB/s 2195014 B/op 10711 allocs/op
BenchmarkRepeated/input_size_5000-8 392 2701453 ns/op 162.88 MB/s 2195074 B/op 10712 allocs/op
BenchmarkRepeated/input_size_10000
BenchmarkRepeated/input_size_10000-8 219 5259815 ns/op 167.31 MB/s 4221108 B/op 20758 allocs/op
BenchmarkRepeated/input_size_10000-8 212 5177215 ns/op 169.98 MB/s 4221232 B/op 20760 allocs/op
BenchmarkRepeated/input_size_10000-8 212 5253915 ns/op 167.49 MB/s 4221303 B/op 20760 allocs/op
BenchmarkRepeated/input_size_10000-8 222 5286982 ns/op 166.45 MB/s 4221027 B/op 20758 allocs/op
BenchmarkRepeated/input_size_10000-8 212 5306389 ns/op 165.84 MB/s 4221115 B/op 20760 allocs/op
BenchmarkRepeated/input_size_10000-8 207 5278139 ns/op 166.73 MB/s 4221125 B/op 20761 allocs/op
BenchmarkRepeated/input_size_10000-8 222 5213650 ns/op 168.79 MB/s 4221129 B/op 20761 allocs/op
BenchmarkRepeated/input_size_10000-8 218 5303988 ns/op 165.91 MB/s 4220946 B/op 20758 allocs/op
BenchmarkRepeated/input_size_10000-8 213 5240200 ns/op 167.93 MB/s 4220985 B/op 20757 allocs/op
BenchmarkRepeated/input_size_10000-8 208 5285554 ns/op 166.49 MB/s 4221086 B/op 20759 allocs/op
BenchmarkRepeated/input_size_20000
BenchmarkRepeated/input_size_20000-8 115 9983275 ns/op 176.29 MB/s 8288363 B/op 40823 allocs/op
BenchmarkRepeated/input_size_20000-8 112 9942367 ns/op 177.02 MB/s 8288068 B/op 40817 allocs/op
BenchmarkRepeated/input_size_20000-8 110 10108681 ns/op 174.11 MB/s 8288440 B/op 40825 allocs/op
BenchmarkRepeated/input_size_20000-8 114 10075659 ns/op 174.68 MB/s 8288224 B/op 40822 allocs/op
BenchmarkRepeated/input_size_20000-8 114 10176893 ns/op 172.94 MB/s 8288669 B/op 40822 allocs/op
BenchmarkRepeated/input_size_20000-8 111 10130699 ns/op 173.73 MB/s 8288174 B/op 40819 allocs/op
BenchmarkRepeated/input_size_20000-8 114 10004131 ns/op 175.93 MB/s 8288453 B/op 40824 allocs/op
BenchmarkRepeated/input_size_20000-8 114 10021144 ns/op 175.63 MB/s 8288623 B/op 40830 allocs/op
BenchmarkRepeated/input_size_20000-8 111 10057201 ns/op 175.00 MB/s 8288203 B/op 40822 allocs/op
BenchmarkRepeated/input_size_20000-8 110 9996611 ns/op 176.06 MB/s 8288558 B/op 40827 allocs/op
PASS
ok github.com/CaduceusMetaverseProtocol/MetaProtocol/benchmark 116.139s
package benchmark_test
import (
"fmt"
"math"
"math/big"
"sort"
"testing"
"github.com/ethereum/go-ethereum/crypto"
)
//date && go test -v -run BenchmarkHello -bench=BenchmarkHello -benchtime=3s -benchmem && date
//go test -v -run BenchmarkAnyTxEth -bench BenchmarkRepeated -benchmem -count 10 | tee RepeatedTxEthAsAny.txt
// go test -v -run BenchmarkHello -bench BenchmarkHello -benchmem -count 10 | tee RepeatedTxEthAsAny.txt
func BenchmarkHello(b *testing.B) {
// b.Log(b.N)
// //b.Logf("begin time: %s \n", time.Now())
// b.ResetTimer()
local, _ := crypto.HexToECDSA("FD5CC6F5E7E2805E920AC5DC83D5AF1106F9C92F0C04F9D5E1FD4261B4B4464A")
// publicKey := local.Public()
// publicKeyECDSA, _ := publicKey.(*ecdsa.PublicKey)
//fromAddr := crypto.PubkeyToAddress(*publicKeyECDSA)
remote, _ := crypto.GenerateKey()
tx, err := pricedTransaction(crypto.PubkeyToAddress(remote.PublicKey), 0, 100000, big.NewInt(1), local)
if err != nil {
b.Fatal(err)
}
for i := 0; i < b.N; i++ {
//b.Logf("idx %d time: %s \n", i, time.Now())
fmt.Sprintf("%v", tx)
}
//b.StopTimer()
//b.Logf("end time: %s \n", time.Now())
// var compares int64
// for i := 0; i < b.N; i++ {
// s := []int{5, 4, 3, 2, 1}
// sort.Slice(s, func(i, j int) bool {
// compares++
// return s[i] < s[j]
// })
// }
// This metric is per-operation, so divide by b.N and
// report it as a "/op" unit.
// b.ReportMetric(float64(compares)/float64(b.N), "compares/op")
}
func BenchmarkCalculate(b *testing.B) {
for i := 0; i < b.N; i++ {
Calculate(2)
}
}
// Calculate returns x + 2.
func Calculate(x int) (result int) {
result = x + 2
return result
}
func primeNumbers(max int) []int {
var primes []int
for i := 2; i < max; i++ {
isPrime := true
for j := 2; j <= int(math.Sqrt(float64(i))); j++ {
if i%j == 0 {
isPrime = false
break
}
}
if isPrime {
primes = append(primes, i)
}
}
return primes
}
var num = 1000
// func BenchmarkPrimeNumbers(b *testing.B) {
// for i := 0; i < b.N; i++ {
// primeNumbers(num)
// }
// }
var table = []struct {
input int
}{
{input: 100},
{input: 1000},
{input: 74382},
{input: 382399},
}
func BenchmarkPrimeNumbers(b *testing.B) {
for _, v := range table {
b.Run(fmt.Sprintf("input_size_%d", v.input), func(b *testing.B) {
for i := 0; i < b.N; i++ {
//primeNumbers(v.input)
sieveOfEratosthenes(v.input)
}
})
}
}
func sieveOfEratosthenes(max int) []int {
b := make([]bool, max)
var primes []int
for i := 2; i < max; i++ {
if b[i] {
continue
}
primes = append(primes, i)
for k := i * i; k < max; k += i {
b[k] = true
}
}
return primes
}
// main_test.go
func BenchmarkSieveOfErastosthenes(b *testing.B) {
for _, v := range table {
b.Run(fmt.Sprintf("input_size_%d", v.input), func(b *testing.B) {
for i := 0; i < b.N; i++ {
sieveOfEratosthenes(v.input)
}
})
}
}
func TestReportMetric(t *testing.T) {
res := testing.Benchmark(func(b *testing.B) {
b.ReportMetric(12345, "ns/op")
b.ReportMetric(0.2, "frobs/op")
})
// Test built-in overriding.
if res.NsPerOp() != 12345 {
t.Errorf("NsPerOp: expected %v, actual %v", 12345, res.NsPerOp())
}
// Test stringing.
res.N = 1 // Make the output stable
want := " 1\t 12345 ns/op\t 0.2000 frobs/op"
if want != res.String() {
t.Errorf("expected %q, actual %q", want, res.String())
}
}
// go test -v -run BenchmarkMetric -bench BenchmarkMetric -benchmem
func BenchmarkMetric(b *testing.B) {
var compares int64
for i := 0; i < b.N; i++ {
s := []int{5, 4, 3, 2, 1}
sort.Slice(s, func(i, j int) bool {
compares++
return s[i] < s[j]
})
}
// This metric is per-operation, so divide by b.N and
// report it as a "/op" unit.
//b.ReportMetric(float64(compares)/float64(b.N), "compares/op")
// This metric is per-operation, so divide by b.N and
// report it as a "/op" unit.
//b.ReportMetric(float64(compares)/float64(b.N), "compares/op")
// This metric is per-time, so divide by b.Elapsed and
// report it as a "/ns" unit.
//b.ReportMetric(float64(compares)/float64(b.Elapsed().Nanoseconds()), "compares/ns")
}
func ExampleB_ReportMetric() {
// This reports a custom benchmark metric relevant to a
// specific algorithm (in this case, sorting).
testing.Benchmark(func(b *testing.B) {
var compares int64
for i := 0; i < b.N; i++ {
s := []int{5, 4, 3, 2, 1}
sort.Slice(s, func(i, j int) bool {
compares++
return s[i] < s[j]
})
}
// This metric is per-operation, so divide by b.N and
// report it as a "/op" unit.
b.ReportMetric(float64(compares)/float64(b.N), "compares/op")
})
}
// func TestBRun(t *T) {
// work := func(b *B) {
// for i := 0; i < b.N; i++ {
// time.Sleep(time.Nanosecond)
// }
// }
// testCases := []struct {
// desc string
// failed bool
// chatty bool
// output string
// f func(*B)
// }{{
// desc: "simulate sequential run of subbenchmarks.",
// f: func(b *B) {
// b.Run("", func(b *B) { work(b) })
// time1 := b.result.NsPerOp()
// b.Run("", func(b *B) { work(b) })
// time2 := b.result.NsPerOp()
// if time1 >= time2 {
// t.Errorf("no time spent in benchmark t1 >= t2 (%d >= %d)", time1, time2)
// }
// },
// }, {
// desc: "bytes set by all benchmarks",
// f: func(b *B) {
// b.Run("", func(b *B) { b.SetBytes(10); work(b) })
// b.Run("", func(b *B) { b.SetBytes(10); work(b) })
// if b.result.Bytes != 20 {
// t.Errorf("bytes: got: %d; want 20", b.result.Bytes)
// }
// },
// }, {
// desc: "bytes set by some benchmarks",
// // In this case the bytes result is meaningless, so it must be 0.
// f: func(b *B) {
// b.Run("", func(b *B) { b.SetBytes(10); work(b) })
// b.Run("", func(b *B) { work(b) })
// b.Run("", func(b *B) { b.SetBytes(10); work(b) })
// if b.result.Bytes != 0 {
// t.Errorf("bytes: got: %d; want 0", b.result.Bytes)
// }
// },
// }, {
// desc: "failure carried over to root",
// failed: true,
// output: "--- FAIL: root",
// f: func(b *B) { b.Fail() },
// }, {
// desc: "skipping without message, chatty",
// chatty: true,
// output: "--- SKIP: root",
// f: func(b *B) { b.SkipNow() },
// }, {
// desc: "chatty with recursion",
// chatty: true,
// f: func(b *B) {
// b.Run("", func(b *B) {
// b.Run("", func(b *B) {})
// })
// },
// }, {
// desc: "skipping without message, not chatty",
// f: func(b *B) { b.SkipNow() },
// }, {
// desc: "skipping after error",
// failed: true,
// output: `
// --- FAIL: root
// sub_test.go:NNN: an error
// sub_test.go:NNN: skipped`,
// f: func(b *B) {
// b.Error("an error")
// b.Skip("skipped")
// },
// }, {
// desc: "memory allocation",
// f: func(b *B) {
// const bufSize = 256
// alloc := func(b *B) {
// var buf [bufSize]byte
// for i := 0; i < b.N; i++ {
// _ = append([]byte(nil), buf[:]...)
// }
// }
// b.Run("", func(b *B) {
// alloc(b)
// b.ReportAllocs()
// })
// b.Run("", func(b *B) {
// alloc(b)
// b.ReportAllocs()
// })
// // runtime.MemStats sometimes reports more allocations than the
// // benchmark is responsible for. Luckily the point of this test is
// // to ensure that the results are not underreported, so we can
// // simply verify the lower bound.
// if got := b.result.MemAllocs; got < 2 {
// t.Errorf("MemAllocs was %v; want 2", got)
// }
// if got := b.result.MemBytes; got < 2*bufSize {
// t.Errorf("MemBytes was %v; want %v", got, 2*bufSize)
// }
// },
// }, {
// desc: "cleanup is called",
// f: func(b *B) {
// var calls, cleanups, innerCalls, innerCleanups int
// b.Run("", func(b *B) {
// calls++
// b.Cleanup(func() {
// cleanups++
// })
// b.Run("", func(b *B) {
// b.Cleanup(func() {
// innerCleanups++
// })
// innerCalls++
// })
// work(b)
// })
// if calls == 0 || calls != cleanups {
// t.Errorf("mismatched cleanups; got %d want %d", cleanups, calls)
// }
// if innerCalls == 0 || innerCalls != innerCleanups {
// t.Errorf("mismatched cleanups; got %d want %d", cleanups, calls)
// }
// },
// }, {
// desc: "cleanup is called on failure",
// failed: true,
// f: func(b *B) {
// var calls, cleanups int
// b.Run("", func(b *B) {
// calls++
// b.Cleanup(func() {
// cleanups++
// })
// b.Fatalf("failure")
// })
// if calls == 0 || calls != cleanups {
// t.Errorf("mismatched cleanups; got %d want %d", cleanups, calls)
// }
// },
// }}
// for _, tc := range testCases {
// t.Run(tc.desc, func(t *T) {
// var ok bool
// buf := &bytes.Buffer{}
// // This is almost like the Benchmark function, except that we override
// // the benchtime and catch the failure result of the subbenchmark.
// root := &B{
// common: common{
// signal: make(chan bool),
// name: "root",
// w: buf,
// },
// benchFunc: func(b *B) { ok = b.Run("test", tc.f) }, // Use Run to catch failure.
// benchTime: durationOrCountFlag{d: 1 * time.Microsecond},
// }
// if tc.chatty {
// root.chatty = newChattyPrinter(root.w)
// }
// root.runN(1)
// if ok != !tc.failed {
// t.Errorf("%s:ok: got %v; want %v", tc.desc, ok, !tc.failed)
// }
// if !ok != root.Failed() {
// t.Errorf("%s:root failed: got %v; want %v", tc.desc, !ok, root.Failed())
// }
// // All tests are run as subtests
// if root.result.N != 1 {
// t.Errorf("%s: N for parent benchmark was %d; want 1", tc.desc, root.result.N)
// }
// got := strings.TrimSpace(buf.String())
// want := strings.TrimSpace(tc.output)
// re := makeRegexp(want)
// if ok, err := regexp.MatchString(re, got); !ok || err != nil {
// t.Errorf("%s:output:\ngot:\n%s\nwant:\n%s", tc.desc, got, want)
// }
// })
// }
// }
package benchmark_test
import (
"bytes"
"context"
"crypto/ecdsa"
"sync"
"math/big"
"testing"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/protobuf/types/known/anypb"
"google.golang.org/protobuf/types/known/emptypb"
base "github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/base/v1"
ring "github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/ring/v1"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
)
func pricedTransaction(to common.Address, nonce uint64, gaslimit uint64, gasprice *big.Int, key *ecdsa.PrivateKey) (*types.Transaction, error) {
return types.SignTx(types.NewTransaction(nonce, to, big.NewInt(100), gaslimit, gasprice, nil), types.HomesteadSigner{}, key)
}
// go test -v -run EthTx -bench=. -benchtime=3s
// go test -v -run BenchmarkAnyTxEth -bench BenchmarkAnyTxEth -benchtime=3s -benchmem
// go test -v -run BenchmarkAnyTxStd -bench BenchmarkAnyTxStd -benchtime=3s -benchmem
// go test -v -run BenchmarkEthTx -bench BenchmarkEthTx -benchtime=3s -benchmem
// go test -v -run BenchmarkStdTx -bench BenchmarkStdTx -benchtime=3s -benchmem
//// go test -v -run BenchmarkAnyTx -bench BenchmarkAnyTx -benchtime=3s -benchmem
// go test -v -run BenchmarkBytesEth -bench BenchmarkBytesEth -benchtime=3s -benchmem
// go test -v -run BenchmarkEmpty -bench BenchmarkEmpty -benchtime=3s -benchmem
// go test -v -run BenchmarkEmptyMsg -bench BenchmarkEmptyMsg -benchtime=3s -benchmem
// go test -v -run BenchmarkAnyTxEth -bench BenchmarkAnyTxEth -benchtime=20000x -benchmem
// go test -v -run BenchmarkAnyTxStd -bench BenchmarkAnyTxStd -benchtime=20000x -benchmem
// go test -v -run BenchmarkEthTx -bench BenchmarkEthTx -benchtime=20000x -benchmem
// go test -v -run BenchmarkStdTx -bench BenchmarkStdTx -benchtime=20000x -benchmem
//// go test -v -run BenchmarkAnyTx -bench BenchmarkAnyTx -benchtime=20000x -benchmem
// go test -v -run BenchmarkBytesEth -bench BenchmarkBytesEth -benchtime=20000x -benchmem
// go test -v -run BenchmarkEmpty -bench BenchmarkEmpty -benchtime=20000x -benchmem
// go test -v -run BenchmarkEmptyMsg -bench BenchmarkEmptyMsg -benchtime=20000x -benchmem
//BenchmarkEmptyMsg
// go test -v -run BenchmarkEthTx -bench BenchmarkEthTx -benchtime=1s
// go test -v -run BenchmarkStdTx -bench BenchmarkStdTx -benchtime=1s
// go test -v -run BenchmarkAnyTx -bench BenchmarkAnyTx -benchtime=1s
// go test -v -run BenchmarkBytesEth -bench BenchmarkBytesEth -benchtime=1s
// go test -v -run BenchmarkEthTx -bench BenchmarkEthTx -benchtime=1x
// go test -v -run BenchmarkStdTx -bench BenchmarkStdTx -benchtime=1x
// go test -v -run BenchmarkAnyTx -bench BenchmarkAnyTx -benchtime=1x
// go test -v -run BenchmarkBytesEth -bench BenchmarkBytesEth -benchtime=1x
// go test -v -run BenchmarkEthTx -bench BenchmarkEthTx -benchtime=100x
// go test -v -run BenchmarkStdTx -bench BenchmarkStdTx -benchtime=100x
// go test -v -run BenchmarkAnyTx -bench BenchmarkAnyTx -benchtime=100x
// go test -v -run BenchmarkBytesEth -bench BenchmarkBytesEth -benchtime=100x
// go test -v -run BenchmarkEthTx -bench BenchmarkEthTx -benchtime=100x -benchmem
// go test -v -run BenchmarkStdTx -bench BenchmarkStdTx -benchtime=100x -benchmem
// go test -v -run BenchmarkAnyTx -bench BenchmarkAnyTx -benchtime=100x -benchmem
// go test -v -run BenchmarkBytesEth -bench BenchmarkBytesEth -benchtime=100x -benchmem
// go test -v -run TestGrpcServer -timeout 0
//BenchmarkAny
// go test -v -run Any -bench=. -benchtime=3s
//var once sync.Once
// var tx *types.Transaction
// var fromAddr common.Address
// var local, remote *ecdsa.PrivateKey
// func int() {
// local, _ := crypto.HexToECDSA("FD5CC6F5E7E2805E920AC5DC83D5AF1106F9C92F0C04F9D5E1FD4261B4B4464A")
// publicKey := local.Public()
// publicKeyECDSA, _ := publicKey.(*ecdsa.PublicKey)
// fromAddr = crypto.PubkeyToAddress(*publicKeyECDSA)
// remote, _ := crypto.GenerateKey()
// var err error
// tx, err = pricedTransaction(crypto.PubkeyToAddress(remote.PublicKey), 0, 100000, big.NewInt(1), local)
// if err != nil {
// fmt.Println("pricedTransaction", err.Error())
// }
// }
// var count int64
// var countParallel int64
var onceHash sync.Once
func BenchmarkEmpty(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
conn, err := grpc.Dial("127.0.0.1:9006", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
b.Fatal(err)
}
defer conn.Close()
c := ring.NewRingServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
res, err := c.SendEmpty(ctx, &emptypb.Empty{})
if err != nil {
b.Fatal(err)
}
_ = res
}
})
}
func BenchmarkEmptyMsg(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
conn, err := grpc.Dial("127.0.0.1:9006", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
b.Fatal(err)
}
defer conn.Close()
c := ring.NewRingServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
c.SendEmptyMsg(ctx, &ring.EmptyRequest{})
res, err := c.SendEmpty(ctx, &emptypb.Empty{})
if err != nil {
b.Fatal(err)
}
_ = res
}
})
}
func BenchmarkEthTx(b *testing.B) {
b.Logf("b.N: %d\n", b.N)
local, err := crypto.HexToECDSA("FD5CC6F5E7E2805E920AC5DC83D5AF1106F9C92F0C04F9D5E1FD4261B4B4464A")
if err != nil {
b.Fatal(err)
}
publicKey := local.Public()
publicKeyECDSA, _ := publicKey.(*ecdsa.PublicKey)
fromAddr := crypto.PubkeyToAddress(*publicKeyECDSA)
remote, err := crypto.GenerateKey()
if err != nil {
b.Fatal(err)
}
tx, err := pricedTransaction(crypto.PubkeyToAddress(remote.PublicKey), 0, 100000, big.NewInt(1), local)
if err != nil {
b.Fatal(err)
}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
conn, err := grpc.Dial("127.0.0.1:9006", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
b.Fatal(err)
}
defer conn.Close()
c := ring.NewRingServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
inner := base.EthTxData{
AccountNonce: tx.Nonce(),
Price: tx.GasPrice().Bytes(),
GasLimit: tx.Gas(),
Payload: tx.Data(),
}
v, r, sigs := tx.RawSignatureValues()
inner.V = v.Bytes()
inner.R = r.Bytes()
inner.S = sigs.Bytes()
inner.Amount = tx.Value().Bytes()
addr := base.Address{Address: tx.To().Bytes()}
inner.Recipient = &addr
inner.From = fromAddr.Bytes()
res, err := c.SendTxAsEth(ctx, &base.TransactionEth{Tx: &base.EthTx{Inner: &inner}})
if err != nil {
b.Fatal(err)
}
_ = res
if bytes.Compare(tx.Hash().Bytes(), res.TxHash) != 0 {
b.Fatal(err)
}
onceHash.Do(func() {
b.Logf("response: %x local: %x \n", res.TxHash, tx.Hash().Bytes())
})
}
})
}
func BenchmarkStdTx(b *testing.B) {
b.Logf("b.N: %d\n", b.N)
// onceFunc := func() {
local, _ := crypto.HexToECDSA("FD5CC6F5E7E2805E920AC5DC83D5AF1106F9C92F0C04F9D5E1FD4261B4B4464A")
publicKey := local.Public()
publicKeyECDSA, _ := publicKey.(*ecdsa.PublicKey)
fromAddr := crypto.PubkeyToAddress(*publicKeyECDSA)
remote, _ := crypto.GenerateKey()
var err error
tx, err := pricedTransaction(crypto.PubkeyToAddress(remote.PublicKey), 0, 100000, big.NewInt(1), local)
if err != nil {
b.Fatal(err)
}
//}
// once.Do(onceFunc)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
conn, err := grpc.Dial("127.0.0.1:9006", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
b.Fatal(err)
}
defer conn.Close()
c := ring.NewRingServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
inner := base.StdTxData{
AccountNonce: tx.Nonce(),
Price: tx.GasPrice().Bytes(),
GasLimit: tx.Gas(),
Payload: tx.Data(),
}
v, r, sigs := tx.RawSignatureValues()
inner.V = v.Bytes()
inner.R = r.Bytes()
inner.S = sigs.Bytes()
inner.Amount = tx.Value().Bytes()
addr := base.Address{Address: tx.To().Bytes()}
inner.Recipient = &addr
inner.From = fromAddr.Bytes()
res, err := c.SendTxAsStd(ctx, &base.TransactionStd{Tx: &base.StdTx{Inner: &inner}})
if err != nil {
b.Fatal(err)
}
_ = res
//fmt.Printf("%x \n", res.TxHash)
if bytes.Compare(tx.Hash().Bytes(), res.TxHash) != 0 {
b.Fatal(err)
}
onceHash.Do(func() {
b.Logf("response: %x local: %x \n", res.TxHash, tx.Hash().Bytes())
})
}
})
}
func BenchmarkAnyTxEth(b *testing.B) {
// onceFunc := func() {
local, _ := crypto.HexToECDSA("FD5CC6F5E7E2805E920AC5DC83D5AF1106F9C92F0C04F9D5E1FD4261B4B4464A")
publicKey := local.Public()
publicKeyECDSA, _ := publicKey.(*ecdsa.PublicKey)
fromAddr := crypto.PubkeyToAddress(*publicKeyECDSA)
remote, _ := crypto.GenerateKey()
var err error
tx, err := pricedTransaction(crypto.PubkeyToAddress(remote.PublicKey), 0, 100000, big.NewInt(1), local)
if err != nil {
b.Fatal(err)
}
//}
// once.Do(onceFunc)
b.ResetTimer()
// The loop body is executed b.N times total across all goroutines.
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
conn, err := grpc.Dial("127.0.0.1:9006", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
b.Fatal(err)
}
defer conn.Close()
c := ring.NewRingServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
inner := base.EthTxData{
AccountNonce: tx.Nonce(),
Price: tx.GasPrice().Bytes(),
GasLimit: tx.Gas(),
Payload: tx.Data(),
}
v, r, sigs := tx.RawSignatureValues()
inner.V = v.Bytes()
inner.R = r.Bytes()
inner.S = sigs.Bytes()
inner.Amount = tx.Value().Bytes()
addr := base.Address{Address: tx.To().Bytes()}
inner.Recipient = &addr
inner.From = fromAddr.Bytes()
ethTx := base.EthTx{Inner: &inner}
ethTxAsAny, err := anypb.New(&ethTx)
res, err := c.SendTxAsAny(ctx, &base.Transaction{Tx: ethTxAsAny})
if err != nil {
b.Fatal(err)
}
_ = res
if bytes.Compare(tx.Hash().Bytes(), res.TxHash) != 0 {
b.Fatal(err)
}
onceHash.Do(func() {
b.Logf("response: %x local: %x \n", res.TxHash, tx.Hash().Bytes())
})
}
})
}
func BenchmarkAnyTxStd(b *testing.B) {
//onceFunc := func() {
local, _ := crypto.HexToECDSA("FD5CC6F5E7E2805E920AC5DC83D5AF1106F9C92F0C04F9D5E1FD4261B4B4464A")
publicKey := local.Public()
publicKeyECDSA, _ := publicKey.(*ecdsa.PublicKey)
fromAddr := crypto.PubkeyToAddress(*publicKeyECDSA)
remote, _ := crypto.GenerateKey()
tx, err := pricedTransaction(crypto.PubkeyToAddress(remote.PublicKey), 0, 100000, big.NewInt(1), local)
if err != nil {
b.Fatal(err)
}
// }
// once.Do(onceFunc)
b.ResetTimer()
// The loop body is executed b.N times total across all goroutines.
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
conn, err := grpc.Dial("127.0.0.1:9006", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
b.Fatal(err)
}
defer conn.Close()
c := ring.NewRingServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
inner := base.StdTxData{
AccountNonce: tx.Nonce(),
Price: tx.GasPrice().Bytes(),
GasLimit: tx.Gas(),
Payload: tx.Data(),
}
v, r, sigs := tx.RawSignatureValues()
inner.V = v.Bytes()
inner.R = r.Bytes()
inner.S = sigs.Bytes()
inner.Amount = tx.Value().Bytes()
addr := base.Address{Address: tx.To().Bytes()}
inner.Recipient = &addr
inner.From = fromAddr.Bytes()
stdTx := base.StdTx{Inner: &inner}
stdTxAsAny, err := anypb.New(&stdTx)
res, err := c.SendTxAsAny(ctx, &base.Transaction{Tx: stdTxAsAny})
if err != nil {
b.Fatal(err)
}
_ = res
if bytes.Compare(tx.Hash().Bytes(), res.TxHash) != 0 {
b.Fatal(err)
}
onceHash.Do(func() {
b.Logf("response: %x local: %x \n", res.TxHash, tx.Hash().Bytes())
})
}
})
}
func BenchmarkBytesEth(b *testing.B) {
// onceFunc := func() {
local, _ := crypto.HexToECDSA("FD5CC6F5E7E2805E920AC5DC83D5AF1106F9C92F0C04F9D5E1FD4261B4B4464A")
publicKey := local.Public()
publicKeyECDSA, _ := publicKey.(*ecdsa.PublicKey)
fromAddr := crypto.PubkeyToAddress(*publicKeyECDSA)
remote, _ := crypto.GenerateKey()
tx, err := pricedTransaction(crypto.PubkeyToAddress(remote.PublicKey), 0, 100000, big.NewInt(1), local)
if err != nil {
b.Fatal(err)
}
// }
// once.Do(onceFunc)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
conn, err := grpc.Dial("127.0.0.1:9006", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
b.Fatal(err)
}
defer conn.Close()
c := ring.NewRingServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
txAsBytes, err := tx.MarshalBinary()
if err != nil {
b.Fatal(err)
}
res, err := c.SendTxAsBytes(ctx, &base.TransactionBytes{Tx: txAsBytes, From: fromAddr[:]})
if err != nil {
b.Fatal(err)
}
_ = res
if bytes.Compare(tx.Hash().Bytes(), res.TxHash) != 0 {
b.Fatal(err)
}
onceHash.Do(func() {
b.Logf("response: %x local: %x \n", res.TxHash, tx.Hash().Bytes())
})
}
})
}
package benchmark
import (
"bytes"
"context"
"sync"
"testing"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/protobuf/types/known/anypb"
base "github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/base/v1"
ring "github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/ring/v1"
)
// go test -v -run EthTx -bench=. -benchtime=3s
// go test -v -run BenchmarkQueueAnyTx -bench BenchmarkQueueAnyTx -benchtime=3s -benchmem
// go test -v -run BenchmarkQueueEthTx -bench BenchmarkQueueEthTx -benchtime=3s -benchmem
// go test -v -run BenchmarkQueueStdTx -bench BenchmarkQueueStdTx -benchtime=3s -benchmem
// go test -v -run BenchmarkQueueBytesEth -bench BenchmarkQueueBytesEth -benchtime=3s -benchmem
var once sync.Once
var onceHash sync.Once
func BenchmarkQueueEthTx(b *testing.B) {
b.Logf("b.N: %d \n", b.N)
// firstDone := make(chan bool, 1)
// onceFunc := func() {
// go ProduceOriginalTx(firstDone)
// <-firstDone
// }
// once.Do(onceFunc)
//b.StopTimer()
//onceFunc := func() {
txsQueue, err := ProduceOriginalTxByCount(500000)
if err != nil {
b.Fatal(err)
}
originalTxsQueue = txsQueue
//}
//once.Do(onceFunc)
b.ResetTimer()
//b.StartTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
conn, err := grpc.Dial("127.0.0.1:9006", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
b.Fatal(err)
}
defer conn.Close()
c := ring.NewRingServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
tx := <-originalTxsQueue
inner := base.EthTxData{
AccountNonce: tx.Nonce(),
Price: tx.GasPrice().Bytes(),
GasLimit: tx.Gas(),
Payload: tx.Data(),
}
v, r, sigs := tx.RawSignatureValues()
inner.V = v.Bytes()
inner.R = r.Bytes()
inner.S = sigs.Bytes()
inner.Amount = tx.Value().Bytes()
addr := base.Address{Address: tx.To().Bytes()}
inner.Recipient = &addr
inner.From = FromAddr.Bytes()
res, err := c.SendTxAsEth(ctx, &base.TransactionEth{Tx: &base.EthTx{Inner: &inner}})
if err != nil {
b.Fatal(err)
}
_ = res
if bytes.Compare(tx.Hash().Bytes(), res.TxHash) != 0 {
b.Fatal(err)
}
onceHash.Do(func() {
b.Logf("response: %x local: %x \n", res.TxHash, tx.Hash().Bytes())
})
}
})
}
func BenchmarkQueueStdTx(b *testing.B) {
b.Logf("b.N: %d\n", b.N)
// firstDone := make(chan bool, 1)
// onceFunc := func() {
// go ProduceOriginalTx(firstDone)
// <-firstDone
// }
// once.Do(onceFunc)
//onceFunc := func() {
txsQueue, err := ProduceOriginalTxByCount(500000)
if err != nil {
b.Fatal(err)
}
originalTxsQueue = txsQueue
//}
//once.Do(onceFunc)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
conn, err := grpc.Dial("127.0.0.1:9006", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
b.Fatal(err)
}
defer conn.Close()
c := ring.NewRingServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
tx := <-originalTxsQueue
inner := base.StdTxData{
AccountNonce: tx.Nonce(),
Price: tx.GasPrice().Bytes(),
GasLimit: tx.Gas(),
Payload: tx.Data(),
}
v, r, sigs := tx.RawSignatureValues()
inner.V = v.Bytes()
inner.R = r.Bytes()
inner.S = sigs.Bytes()
inner.Amount = tx.Value().Bytes()
addr := base.Address{Address: tx.To().Bytes()}
inner.Recipient = &addr
inner.From = FromAddr.Bytes()
res, err := c.SendTxAsStd(ctx, &base.TransactionStd{Tx: &base.StdTx{Inner: &inner}})
if err != nil {
b.Fatal(err)
}
_ = res
//fmt.Printf("%x \n", res.TxHash)
if bytes.Compare(tx.Hash().Bytes(), res.TxHash) != 0 {
b.Fatal(err)
}
onceHash.Do(func() {
b.Logf("response: %x local: %x \n", res.TxHash, tx.Hash().Bytes())
})
}
})
}
func BenchmarkQueueAnyTx(b *testing.B) {
b.Logf("b.N: %d \n", b.N)
// firstDone := make(chan bool, 1)
// onceFunc := func() {
// go ProduceOriginalTx(firstDone)
// <-firstDone
// }
// once.Do(onceFunc)
//onceFunc := func() {
txsQueue, err := ProduceOriginalTxByCount(500000)
if err != nil {
b.Fatal(err)
}
originalTxsQueue = txsQueue
//}
//once.Do(onceFunc)
b.ResetTimer()
// The loop body is executed b.N times total across all goroutines.
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
conn, err := grpc.Dial("127.0.0.1:9006", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
b.Fatal(err)
}
defer conn.Close()
c := ring.NewRingServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
tx := <-originalTxsQueue
inner := base.EthTxData{
AccountNonce: tx.Nonce(),
Price: tx.GasPrice().Bytes(),
GasLimit: tx.Gas(),
Payload: tx.Data(),
}
v, r, sigs := tx.RawSignatureValues()
inner.V = v.Bytes()
inner.R = r.Bytes()
inner.S = sigs.Bytes()
inner.Amount = tx.Value().Bytes()
addr := base.Address{Address: tx.To().Bytes()}
inner.Recipient = &addr
inner.From = FromAddr.Bytes()
ethTx := base.EthTx{Inner: &inner}
ethTxAsAny, err := anypb.New(&ethTx)
res, err := c.SendTxAsAny(ctx, &base.Transaction{Tx: ethTxAsAny})
if err != nil {
b.Fatal(err)
}
_ = res
if bytes.Compare(tx.Hash().Bytes(), res.TxHash) != 0 {
b.Fatal(err)
}
onceHash.Do(func() {
b.Logf("response: %x local: %x \n", res.TxHash, tx.Hash().Bytes())
})
}
})
}
func BenchmarkQueueBytesEth(b *testing.B) {
b.Logf("b.N: %d \n", b.N)
// firstDone := make(chan bool, 1)
// onceFunc := func() {
// go ProduceOriginalTx(firstDone)
// <-firstDone
// }
// once.Do(onceFunc)
//onceFunc := func() {
txsQueue, err := ProduceOriginalTxByCount(500000)
if err != nil {
b.Fatal(err)
}
originalTxsQueue = txsQueue
//}
//once.Do(onceFunc)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
conn, err := grpc.Dial("127.0.0.1:9006", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
b.Fatal(err)
}
defer conn.Close()
c := ring.NewRingServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
tx := <-originalTxsQueue
txAsBytes, err := tx.MarshalBinary()
if err != nil {
b.Fatal(err)
}
res, err := c.SendTxAsBytes(ctx, &base.TransactionBytes{Tx: txAsBytes, From: FromAddr[:]})
if err != nil {
b.Fatal(err)
}
_ = res
if bytes.Compare(tx.Hash().Bytes(), res.TxHash) != 0 {
b.Fatal(err)
}
onceHash.Do(func() {
b.Logf("response: %x local: %x \n", res.TxHash, tx.Hash().Bytes())
})
}
})
}
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/ring/v1 (interfaces: GreeterClient)
// Package mock_v1 is a generated GoMock package.
package benchmark
import (
context "context"
reflect "reflect"
ringv1 "github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/ring/v1"
gomock "github.com/golang/mock/gomock"
grpc "google.golang.org/grpc"
)
// MockGreeterClient is a mock of GreeterClient interface.
type MockGreeterClient struct {
ctrl *gomock.Controller
recorder *MockGreeterClientMockRecorder
}
// MockGreeterClientMockRecorder is the mock recorder for MockGreeterClient.
type MockGreeterClientMockRecorder struct {
mock *MockGreeterClient
}
// NewMockGreeterClient creates a new mock instance.
func NewMockGreeterClient(ctrl *gomock.Controller) *MockGreeterClient {
mock := &MockGreeterClient{ctrl: ctrl}
mock.recorder = &MockGreeterClientMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockGreeterClient) EXPECT() *MockGreeterClientMockRecorder {
return m.recorder
}
// SayHello mocks base method.
func (m *MockGreeterClient) SayHello(arg0 context.Context, arg1 *ringv1.HelloRequest, arg2 ...grpc.CallOption) (*ringv1.HelloReply, error) {
m.ctrl.T.Helper()
varargs := []interface{}{arg0, arg1}
for _, a := range arg2 {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "SayHello", varargs...)
ret0, _ := ret[0].(*ringv1.HelloReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SayHello indicates an expected call of SayHello.
func (mr *MockGreeterClientMockRecorder) SayHello(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]interface{}{arg0, arg1}, arg2...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SayHello", reflect.TypeOf((*MockGreeterClient)(nil).SayHello), varargs...)
}
package benchmark
import (
"bytes"
"fmt"
"testing"
"text/template"
)
func main() {
benchmarkResult := testing.Benchmark(func(b *testing.B) {
templ := template.Must(template.New("test").Parse("Hello, {{.}}!"))
// RunParallel will create GOMAXPROCS goroutines
// and distribute work among them.
b.RunParallel(func(pb *testing.PB) {
// Each goroutine has its own bytes.Buffer.
var buf bytes.Buffer
for pb.Next() {
// The loop body is executed b.N times total across all goroutines.
buf.Reset()
templ.Execute(&buf, "World")
}
})
})
fmt.Printf("%8d\t%10d ns/op\t%10d B/op\t%10d allocs/op %s total time taken \n", benchmarkResult.N, benchmarkResult.NsPerOp(), benchmarkResult.AllocedBytesPerOp(), benchmarkResult.AllocsPerOp(), benchmarkResult.T)
//fmt.Printf("%s\t%s\n", benchmarkResult.String(), benchmarkResult.MemString())
}
package benchmark
import (
"testing"
ring "github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/ring/v1"
"github.com/golang/mock/gomock"
"google.golang.org/protobuf/proto"
)
//mockgen github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/ring/v1 GreeterClient > benchmark/hw_mock.go
//RingService
//mockgen github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/ring/v1 RingServiceClient > benchmark/ring_mock.go
func TestSendEmptyMsg(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockGreeterClient := NewMockRingServiceClient(ctrl)
mockGreeterClient.EXPECT().SendEmptyMsg(gomock.Any(), &ring.EmptyRequest{}).Return(&ring.EmptyResponse{}, nil).AnyTimes()
// gomock.Any(), // expect any value for first parameter
// gomock.Any(), // expect any value for second parameter
}
type rpcMsg struct {
msg proto.Message
}
// func (r *rpcMsg) Matches(msg interface{}) bool {
// m, ok := msg.(proto.Message)
// if !ok {
// return false
// }
// return proto.Equal(m, r.msg)
// }
// func (r *rpcMsg) String() string {
// return fmt.Sprintf("is %s", r.msg)
// }
func TestHelloWorld(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockGreeterClient := NewMockGreeterClient(ctrl)
req := &ring.HelloRequest{Name: "unit_test"}
mockGreeterClient.EXPECT().SayHello(
gomock.Any(), // expect any value for first parameter
&rpcMsg{msg: req}, // expect any value for second parameter
).Return(&ring.HelloReply{Name: "Mocked RPC"}, nil).AnyTimes()
}
func BenchmarkHelloWorld(b *testing.B) {
ctrl := gomock.NewController(b)
defer ctrl.Finish()
mockGreeterClient := NewMockGreeterClient(ctrl)
req := &ring.HelloRequest{Name: "unit_test"}
b.ResetTimer()
for i := 0; i < b.N; i++ {
mockGreeterClient.EXPECT().SayHello(
gomock.Any(), // expect any value for first parameter
&rpcMsg{msg: req}, // expect any value for second parameter).Return(101)
).Return(&ring.HelloReply{Name: "Mocked RPC"}, nil).AnyTimes()
}
}
goos: linux
goarch: amd64
pkg: github.com/CaduceusMetaverseProtocol/MetaProtocol/benchmark
cpu: Intel(R) Xeon(R) Platinum 8275CL CPU @ 3.00GHz
BenchmarkPrimeNumbers/input_size_100-8 3176238 376.2 ns/op 616 B/op 7 allocs/op
BenchmarkPrimeNumbers/input_size_100-8 3196476 375.8 ns/op 616 B/op 7 allocs/op
BenchmarkPrimeNumbers/input_size_100-8 3165849 375.2 ns/op 616 B/op 7 allocs/op
BenchmarkPrimeNumbers/input_size_100-8 3180127 374.9 ns/op 616 B/op 7 allocs/op
BenchmarkPrimeNumbers/input_size_100-8 3191452 374.7 ns/op 616 B/op 7 allocs/op
BenchmarkPrimeNumbers/input_size_1000-8 486660 2332 ns/op 5112 B/op 10 allocs/op
BenchmarkPrimeNumbers/input_size_1000-8 485665 2356 ns/op 5112 B/op 10 allocs/op
BenchmarkPrimeNumbers/input_size_1000-8 500113 2366 ns/op 5112 B/op 10 allocs/op
BenchmarkPrimeNumbers/input_size_1000-8 494041 2338 ns/op 5112 B/op 10 allocs/op
BenchmarkPrimeNumbers/input_size_1000-8 487268 2358 ns/op 5112 B/op 10 allocs/op
BenchmarkPrimeNumbers/input_size_74382-8 4917 228584 ns/op 341241 B/op 19 allocs/op
BenchmarkPrimeNumbers/input_size_74382-8 4910 228502 ns/op 341241 B/op 19 allocs/op
BenchmarkPrimeNumbers/input_size_74382-8 4935 227803 ns/op 341241 B/op 19 allocs/op
BenchmarkPrimeNumbers/input_size_74382-8 4903 227836 ns/op 341241 B/op 19 allocs/op
BenchmarkPrimeNumbers/input_size_74382-8 5020 230502 ns/op 341241 B/op 19 allocs/op
BenchmarkPrimeNumbers/input_size_382399-8 988 1190875 ns/op 1545468 B/op 24 allocs/op
BenchmarkPrimeNumbers/input_size_382399-8 1030 1187270 ns/op 1545467 B/op 24 allocs/op
BenchmarkPrimeNumbers/input_size_382399-8 1014 1168560 ns/op 1545466 B/op 24 allocs/op
BenchmarkPrimeNumbers/input_size_382399-8 998 1178405 ns/op 1545466 B/op 24 allocs/op
BenchmarkPrimeNumbers/input_size_382399-8 994 1181863 ns/op 1545469 B/op 24 allocs/op
PASS
ok github.com/CaduceusMetaverseProtocol/MetaProtocol/benchmark 26.125s
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Performance Result Comparison</title>
<style>
.benchstat { border-collapse: collapse; }
.benchstat th:nth-child(1) { text-align: left; }
.benchstat tbody td:nth-child(1n+2):not(.note) { text-align: right; padding: 0em 1em; }
.benchstat tr:not(.configs) th { border-top: 1px solid #666; border-bottom: 1px solid #ccc; }
.benchstat .nodelta { text-align: center !important; }
.benchstat .better td.delta { font-weight: bold; }
.benchstat .worse td.delta { font-weight: bold; color: #c00; }
</style>
</head>
<body>
<table class='benchstat oldnew'>
<tr class='configs'><th><th>RepeatedEthTx.txt<th>RepeatedTxEthAsAny.txt
<tbody>
<tr><th><th colspan='2' class='metric'>time/op<th>delta
<tr class='worse'><td>Repeated/input_size_100-8<td>211µs ± 4%<td>214µs ± 5%<td class='delta'>+1.35%<td class='note'>
<tr class='worse'><td>Repeated/input_size_200-8<td>284µs ± 3%<td>284µs ± 4%<td class='delta'>+0.15%<td class='note'>
<tr class='worse'><td>Repeated/input_size_500-8<td>521µs ± 3%<td>524µs ± 4%<td class='delta'>+0.48%<td class='note'>
<tr class='worse'><td>Repeated/input_size_1000-8<td>1.00ms ±11%<td>1.04ms ± 4%<td class='delta'>+3.93%<td class='note'>
<tr class='worse'><td>Repeated/input_size_2000-8<td>1.78ms ±14%<td>1.95ms ± 2%<td class='delta'>+9.25%<td class='note'>
<tr class='worse'><td>Repeated/input_size_5000-8<td>3.99ms ± 3%<td>4.58ms ± 2%<td class='delta'>+14.91%<td class='note'>
<tr class='worse'><td>Repeated/input_size_10000-8<td>7.72ms ± 2%<td>8.86ms ± 3%<td class='delta'>+14.69%<td class='note'>
<tr class='worse'><td>Repeated/input_size_20000-8<td>14.9ms ± 4%<td>17.0ms ± 2%<td class='delta'>+13.45%<td class='note'>
<tr class='unchanged'><td>[Geo mean]<td>1.50ms <td>1.61ms <td class='delta'>+7.10%<td class='note'>
<tr><td>&nbsp;
</tbody>
<tbody>
<tr><th><th colspan='2' class='metric'>speed<th>delta
<tr class='worse'><td>Repeated/input_size_100-8<td>64.2MB/s ± 4%<td>63.3MB/s ± 5%<td class='delta'>−1.31%<td class='note'>
<tr class='worse'><td>Repeated/input_size_200-8<td>95.3MB/s ± 3%<td>95.2MB/s ± 4%<td class='delta'>−0.15%<td class='note'>
<tr class='worse'><td>Repeated/input_size_500-8<td>130MB/s ± 3%<td>129MB/s ± 3%<td class='delta'>−0.45%<td class='note'>
<tr class='worse'><td>Repeated/input_size_1000-8<td>136MB/s ±12%<td>130MB/s ± 4%<td class='delta'>−4.15%<td class='note'>
<tr class='worse'><td>Repeated/input_size_2000-8<td>153MB/s ±13%<td>139MB/s ± 2%<td class='delta'>−8.97%<td class='note'>
<tr class='worse'><td>Repeated/input_size_5000-8<td>169MB/s ± 2%<td>147MB/s ± 3%<td class='delta'>−13.15%<td class='note'>
<tr class='worse'><td>Repeated/input_size_10000-8<td>175MB/s ± 4%<td>152MB/s ± 3%<td class='delta'>−12.70%<td class='note'>
<tr class='worse'><td>Repeated/input_size_20000-8<td>179MB/s ±10%<td>159MB/s ± 2%<td class='delta'>−11.06%<td class='note'>
<tr class='unchanged'><td>[Geo mean]<td>131MB/s <td>122MB/s <td class='delta'>−6.64%<td class='note'>
<tr><td>&nbsp;
</tbody>
<tbody>
<tr><th><th colspan='2' class='metric'>tps<th>delta
<tr class='better'><td>Repeated/input_size_100-8<td>4.74k ± 4%<td>4.68k ± 5%<td class='delta'>−1.32%<td class='note'>
<tr class='better'><td>Repeated/input_size_200-8<td>3.52k ± 3%<td>3.52k ± 4%<td class='delta'>−0.15%<td class='note'>
<tr class='better'><td>Repeated/input_size_500-8<td>1.92k ± 3%<td>1.91k ± 3%<td class='delta'>−0.48%<td class='note'>
<tr class='better'><td>Repeated/input_size_1000-8<td>1.00k ±12%<td>0.96k ± 4%<td class='delta'>−4.15%<td class='note'>
<tr class='better'><td>Repeated/input_size_2000-8<td>565 ±13%<td>514 ± 2%<td class='delta'>−8.97%<td class='note'>
<tr class='better'><td>Repeated/input_size_5000-8<td>251 ± 2%<td>218 ± 3%<td class='delta'>−13.15%<td class='note'>
<tr class='better'><td>Repeated/input_size_10000-8<td>129 ± 4%<td>113 ± 3%<td class='delta'>−12.69%<td class='note'>
<tr class='better'><td>Repeated/input_size_20000-8<td>66.4 ±10%<td>59.0 ± 2%<td class='delta'>−11.09%<td class='note'>
<tr class='unchanged'><td>[Geo mean]<td>667 <td>623 <td class='delta'>−6.64%<td class='note'>
<tr><td>&nbsp;
</tbody>
<tbody>
<tr><th><th colspan='2' class='metric'>alloc/op<th>delta
<tr class='worse'><td>Repeated/input_size_100-8<td>254kB ± 0%<td>254kB ± 0%<td class='delta'>+0.00%<td class='note'>
<tr class='worse'><td>Repeated/input_size_200-8<td>365kB ± 0%<td>365kB ± 0%<td class='delta'>+0.00%<td class='note'>
<tr class='worse'><td>Repeated/input_size_500-8<td>702kB ± 0%<td>702kB ± 0%<td class='delta'>+0.00%<td class='note'>
<tr class='better'><td>Repeated/input_size_1000-8<td>1.23MB ± 0%<td>1.23MB ± 0%<td class='delta'>−0.00%<td class='note'>
<tr class='worse'><td>Repeated/input_size_2000-8<td>2.28MB ± 0%<td>2.28MB ± 0%<td class='delta'>+0.00%<td class='note'>
<tr class='worse'><td>Repeated/input_size_5000-8<td>5.48MB ± 0%<td>5.48MB ± 0%<td class='delta'>+0.00%<td class='note'>
<tr class='worse'><td>Repeated/input_size_10000-8<td>10.8MB ± 0%<td>10.8MB ± 0%<td class='delta'>+0.00%<td class='note'>
<tr class='worse'><td>Repeated/input_size_20000-8<td>21.4MB ± 0%<td>21.4MB ± 0%<td class='delta'>+0.00%<td class='note'>
<tr class='unchanged'><td>[Geo mean]<td>1.97MB <td>1.97MB <td class='delta'>+0.00%<td class='note'>
<tr><td>&nbsp;
</tbody>
<tbody>
<tr><th><th colspan='2' class='metric'>allocs/op<th>delta
<tr class='unchanged'><td>Repeated/input_size_100-8<td>2.12k ± 0%<td>2.12k ± 0%<td class='delta'>0.00%<td class='note'>
<tr class='unchanged'><td>Repeated/input_size_200-8<td>3.62k ± 0%<td>3.62k ± 0%<td class='delta'>0.00%<td class='note'>
<tr class='unchanged'><td>Repeated/input_size_500-8<td>8.14k ± 0%<td>8.14k ± 0%<td class='delta'>0.00%<td class='note'>
<tr class='better'><td>Repeated/input_size_1000-8<td>15.6k ± 0%<td>15.6k ± 0%<td class='delta'>−0.00%<td class='note'>
<tr class='better'><td>Repeated/input_size_2000-8<td>30.7k ± 0%<td>30.7k ± 0%<td class='delta'>−0.00%<td class='note'>
<tr class='worse'><td>Repeated/input_size_5000-8<td>75.7k ± 0%<td>75.7k ± 0%<td class='delta'>+0.00%<td class='note'>
<tr class='worse'><td>Repeated/input_size_10000-8<td>151k ± 0%<td>151k ± 0%<td class='delta'>+0.00%<td class='note'>
<tr class='worse'><td>Repeated/input_size_20000-8<td>301k ± 0%<td>301k ± 0%<td class='delta'>+0.00%<td class='note'>
<tr class='unchanged'><td>[Geo mean]<td>23.8k <td>23.8k <td class='delta'>+0.00%<td class='note'>
<tr><td>&nbsp;
</tbody>
</table>
</body>
</html>
goos: linux
goarch: amd64
pkg: github.com/CaduceusMetaverseProtocol/MetaProtocol/benchmark
cpu: Intel(R) Xeon(R) Platinum 8275CL CPU @ 3.00GHz
BenchmarkQueueEthTx-8 7838 149282 ns/op
--- BENCH: BenchmarkQueueEthTx-8
grpc-queue-tx_test.go:30: b.N: 1
grpc-queue-tx_test.go:109: response: 9fa50e67f63b7059a92a5ffe0f4f8201e88c38b572364f8140275b2f445c1b8f local: 9fa50e67f63b7059a92a5ffe0f4f8201e88c38b572364f8140275b2f445c1b8f
grpc-queue-tx_test.go:30: b.N: 100
grpc-queue-tx_test.go:30: b.N: 3288
grpc-queue-tx_test.go:30: b.N: 5540
grpc-queue-tx_test.go:30: b.N: 7838
BenchmarkQueueEthTx-8 10000 156028 ns/op
--- BENCH: BenchmarkQueueEthTx-8
grpc-queue-tx_test.go:30: b.N: 1
grpc-queue-tx_test.go:30: b.N: 100
grpc-queue-tx_test.go:30: b.N: 10000
BenchmarkQueueEthTx-8 10000 154042 ns/op
--- BENCH: BenchmarkQueueEthTx-8
grpc-queue-tx_test.go:30: b.N: 1
grpc-queue-tx_test.go:30: b.N: 100
grpc-queue-tx_test.go:30: b.N: 10000
BenchmarkQueueStdTx-8 10000 157969 ns/op
--- BENCH: BenchmarkQueueStdTx-8
grpc-queue-tx_test.go:118: b.N: 1
grpc-queue-tx_test.go:118: b.N: 100
grpc-queue-tx_test.go:118: b.N: 10000
BenchmarkQueueStdTx-8 10000 150678 ns/op
--- BENCH: BenchmarkQueueStdTx-8
grpc-queue-tx_test.go:118: b.N: 1
grpc-queue-tx_test.go:118: b.N: 100
grpc-queue-tx_test.go:118: b.N: 10000
BenchmarkQueueStdTx-8 10000 153660 ns/op
--- BENCH: BenchmarkQueueStdTx-8
grpc-queue-tx_test.go:118: b.N: 1
grpc-queue-tx_test.go:118: b.N: 100
grpc-queue-tx_test.go:118: b.N: 10000
BenchmarkQueueAnyTx-8
\ No newline at end of file
package benchmark
import (
"crypto/ecdsa"
"math/big"
"sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
)
func buildSendTx(nonce uint64, to common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte, chainId *big.Int, privateKey *ecdsa.PrivateKey) (*types.Transaction, error) {
return buildTx(nonce, to, amount, gasLimit, gasPrice, data, chainId, privateKey)
}
func buildOriginalTx(nonce uint64, to common.Address, amount int64, chainId *big.Int, privateKey *ecdsa.PrivateKey) (*types.Transaction, error) {
return buildTx(nonce, to, big.NewInt(amount), 0, big.NewInt(0), nil, chainId, privateKey)
}
func buildTx(nonce uint64, to common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte, chainId *big.Int, privateKey *ecdsa.PrivateKey) (*types.Transaction, error) {
tx := types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, data)
if privateKey != nil {
signedTx, err := types.SignTx(tx, types.NewEIP155Signer(chainId), privateKey)
if err != nil {
return nil, err
}
tx = signedTx
}
return tx, nil
}
type EthClient struct {
PrivateKey *ecdsa.PrivateKey
FromAddr common.Address
NodeUrl string
Nonce uint64
GasPrice *big.Int
ChainId *big.Int
GasLimit uint64
}
var originalTxPrivateKey string = "9e0944f587e1043d6e303644738b0c7c77ed15b176ca574ed0be40c0b9bbdc3a"
var toAddress common.Address = common.HexToAddress("0x0071B39fd266F8aeF392fb50F078A233b2218a0b")
var originalTxsQueue chan *types.Transaction //= make(chan *types.Transaction, 50000)
var originalTxParam EthClient
var FromAddr common.Address
// type TxWithFrom struct {
// From []byte
// Tx []byte
// }
func init() {
originalTxPrivatekeyAsECDSA, err := crypto.HexToECDSA(originalTxPrivateKey)
if err != nil {
panic(err)
}
originalTxPublicKey := originalTxPrivatekeyAsECDSA.Public()
originalTxPublicKeyECDSA, ok := originalTxPublicKey.(*ecdsa.PublicKey)
if !ok {
panic("publicKey.(*ecdsa.PublicKey) not ok")
}
originalTxFromAddress := crypto.PubkeyToAddress(*originalTxPublicKeyECDSA)
originalTxParam = EthClient{
PrivateKey: originalTxPrivatekeyAsECDSA,
FromAddr: originalTxFromAddress,
Nonce: 0,
}
FromAddr = originalTxFromAddress
}
var doneOnce sync.Once
func ProduceOriginalTx(firstdone chan bool) error {
if originalTxsQueue == nil {
originalTxsQueue = make(chan *types.Transaction, 50000)
}
for {
if len(originalTxsQueue) == 50000 {
doneOnce.Do(func() {
firstdone <- true
})
}
tx, err := buildOriginalTx(originalTxParam.Nonce, toAddress, 0, big.NewInt(256), nil)
if err != nil {
return err
}
originalTxParam.Nonce += 1
originalTxsQueue <- tx
}
}
func ProduceOriginalTxByCount(count int64) (chan *types.Transaction, error) {
var txsQueue chan *types.Transaction = make(chan *types.Transaction, count)
for i := 0; int64(i) < count; i++ {
tx, err := buildOriginalTx(originalTxParam.Nonce, toAddress, 0, big.NewInt(256), nil)
if err != nil {
return nil, err
}
originalTxParam.Nonce += 1
txsQueue <- tx
}
return txsQueue, nil
}
// go test -v -run EthTx -bench=. -benchtime=3s
// go test -v -run BenchmarkAnyTxEth -bench BenchmarkAnyTxEth -benchtime=3s -benchmem -cover
// go test -v -run BenchmarkAnyTxStd -bench BenchmarkAnyTxStd -benchtime=3s -benchmem -cover
// go test -v -run BenchmarkEthTx -bench BenchmarkEthTx -benchtime=3s -benchmem
// go test -v -run BenchmarkStdTx -bench BenchmarkStdTx -benchtime=3s -benchmem
//// go test -v -run BenchmarkAnyTx -bench BenchmarkAnyTx -benchtime=3s -benchmem
// go test -v -run BenchmarkBytesEth -bench BenchmarkBytesEth -benchtime=3s -benchmem
// go test -v -run BenchmarkEmpty -bench BenchmarkEmpty -benchtime=3s -benchmem
// go test -v -run BenchmarkEmptyMsg -bench BenchmarkEmptyMsg -benchtime=3s -benchmem
// go test -v -run BenchmarkAnyTxEth -bench BenchmarkAnyTxEth -benchtime=20000x -benchmem
// go test -v -run BenchmarkAnyTxStd -bench BenchmarkAnyTxStd -benchtime=20000x -benchmem
// go test -v -run BenchmarkEthTx -bench BenchmarkEthTx -benchtime=20000x -benchmem
// go test -v -run BenchmarkStdTx -bench BenchmarkStdTx -benchtime=20000x -benchmem
//// go test -v -run BenchmarkAnyTx -bench BenchmarkAnyTx -benchtime=20000x -benchmem
// go test -v -run BenchmarkBytesEth -bench BenchmarkBytesEth -benchtime=20000x -benchmem
// go test -v -run BenchmarkEmpty -bench BenchmarkEmpty -benchtime=20000x -benchmem
// go test -v -run BenchmarkEmptyMsg -bench BenchmarkEmptyMsg -benchtime=20000x -benchmem
//BenchmarkEmptyMsg
// go test -v -run BenchmarkEthTx -bench BenchmarkEthTx -benchtime=1s
// go test -v -run BenchmarkStdTx -bench BenchmarkStdTx -benchtime=1s
// go test -v -run BenchmarkAnyTx -bench BenchmarkAnyTx -benchtime=1s
// go test -v -run BenchmarkBytesEth -bench BenchmarkBytesEth -benchtime=1s
// go test -v -run BenchmarkEthTx -bench BenchmarkEthTx -benchtime=1x
// go test -v -run BenchmarkStdTx -bench BenchmarkStdTx -benchtime=1x
// go test -v -run BenchmarkAnyTx -bench BenchmarkAnyTx -benchtime=1x
// go test -v -run BenchmarkBytesEth -bench BenchmarkBytesEth -benchtime=1x
// go test -v -run BenchmarkEthTx -bench BenchmarkEthTx -benchtime=100x
// go test -v -run BenchmarkStdTx -bench BenchmarkStdTx -benchtime=100x
// go test -v -run BenchmarkAnyTx -bench BenchmarkAnyTx -benchtime=100x
// go test -v -run BenchmarkBytesEth -bench BenchmarkBytesEth -benchtime=100x
// go test -v -run BenchmarkEthTx -bench BenchmarkEthTx -benchtime=100x -benchmem
// go test -v -run BenchmarkStdTx -bench BenchmarkStdTx -benchtime=100x -benchmem
// go test -v -run BenchmarkAnyTx -bench BenchmarkAnyTx -benchtime=100x -benchmem
// go test -v -run BenchmarkBytesEth -bench BenchmarkBytesEth -benchtime=100x -benchmem
// go test -v -run TestGrpcServer -timeout 0
//BenchmarkAny
// go test -v -run Any -bench=. -benchtime=3s
// go test -v -run EthTx -bench=. -benchtime=3s
// go test -v -run Bench -bench BenchmarkQueueAnyTx -benchtime=3s -benchmem
// go test -v -run Bench -bench BenchmarkQueueEthTx -benchtime=3s -benchmem
// go test -v -run Bench -bench BenchmarkQueueStdTx -benchtime=3s -benchmem
// go test -v -run Bench -bench BenchmarkQueueBytesEth -benchtime=3s -benchmem
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/ring/v1 (interfaces: RingServiceClient)
// Package mock_v1 is a generated GoMock package.
package benchmark
import (
context "context"
reflect "reflect"
basev1 "github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/base/v1"
ringv1 "github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/ring/v1"
gomock "github.com/golang/mock/gomock"
grpc "google.golang.org/grpc"
emptypb "google.golang.org/protobuf/types/known/emptypb"
)
// MockRingServiceClient is a mock of RingServiceClient interface.
type MockRingServiceClient struct {
ctrl *gomock.Controller
recorder *MockRingServiceClientMockRecorder
}
// MockRingServiceClientMockRecorder is the mock recorder for MockRingServiceClient.
type MockRingServiceClientMockRecorder struct {
mock *MockRingServiceClient
}
// NewMockRingServiceClient creates a new mock instance.
func NewMockRingServiceClient(ctrl *gomock.Controller) *MockRingServiceClient {
mock := &MockRingServiceClient{ctrl: ctrl}
mock.recorder = &MockRingServiceClientMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockRingServiceClient) EXPECT() *MockRingServiceClientMockRecorder {
return m.recorder
}
// Nonce mocks base method.
func (m *MockRingServiceClient) Nonce(arg0 context.Context, arg1 *ringv1.NonceRequest, arg2 ...grpc.CallOption) (*ringv1.NonceResponse, error) {
m.ctrl.T.Helper()
varargs := []interface{}{arg0, arg1}
for _, a := range arg2 {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "Nonce", varargs...)
ret0, _ := ret[0].(*ringv1.NonceResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Nonce indicates an expected call of Nonce.
func (mr *MockRingServiceClientMockRecorder) Nonce(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]interface{}{arg0, arg1}, arg2...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Nonce", reflect.TypeOf((*MockRingServiceClient)(nil).Nonce), varargs...)
}
// SendEmpty mocks base method.
func (m *MockRingServiceClient) SendEmpty(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc.CallOption) (*emptypb.Empty, error) {
m.ctrl.T.Helper()
varargs := []interface{}{arg0, arg1}
for _, a := range arg2 {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "SendEmpty", varargs...)
ret0, _ := ret[0].(*emptypb.Empty)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SendEmpty indicates an expected call of SendEmpty.
func (mr *MockRingServiceClientMockRecorder) SendEmpty(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]interface{}{arg0, arg1}, arg2...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendEmpty", reflect.TypeOf((*MockRingServiceClient)(nil).SendEmpty), varargs...)
}
// SendEmptyMsg mocks base method.
func (m *MockRingServiceClient) SendEmptyMsg(arg0 context.Context, arg1 *ringv1.EmptyRequest, arg2 ...grpc.CallOption) (*ringv1.EmptyResponse, error) {
m.ctrl.T.Helper()
varargs := []interface{}{arg0, arg1}
for _, a := range arg2 {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "SendEmptyMsg", varargs...)
ret0, _ := ret[0].(*ringv1.EmptyResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SendEmptyMsg indicates an expected call of SendEmptyMsg.
func (mr *MockRingServiceClientMockRecorder) SendEmptyMsg(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]interface{}{arg0, arg1}, arg2...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendEmptyMsg", reflect.TypeOf((*MockRingServiceClient)(nil).SendEmptyMsg), varargs...)
}
// SendTxAsAny mocks base method.
func (m *MockRingServiceClient) SendTxAsAny(arg0 context.Context, arg1 *basev1.Transaction, arg2 ...grpc.CallOption) (*ringv1.SendRawTransactionResponse, error) {
m.ctrl.T.Helper()
varargs := []interface{}{arg0, arg1}
for _, a := range arg2 {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "SendTxAsAny", varargs...)
ret0, _ := ret[0].(*ringv1.SendRawTransactionResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SendTxAsAny indicates an expected call of SendTxAsAny.
func (mr *MockRingServiceClientMockRecorder) SendTxAsAny(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]interface{}{arg0, arg1}, arg2...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendTxAsAny", reflect.TypeOf((*MockRingServiceClient)(nil).SendTxAsAny), varargs...)
}
// SendTxAsBytes mocks base method.
func (m *MockRingServiceClient) SendTxAsBytes(arg0 context.Context, arg1 *basev1.TransactionBytes, arg2 ...grpc.CallOption) (*ringv1.SendRawTransactionResponse, error) {
m.ctrl.T.Helper()
varargs := []interface{}{arg0, arg1}
for _, a := range arg2 {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "SendTxAsBytes", varargs...)
ret0, _ := ret[0].(*ringv1.SendRawTransactionResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SendTxAsBytes indicates an expected call of SendTxAsBytes.
func (mr *MockRingServiceClientMockRecorder) SendTxAsBytes(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]interface{}{arg0, arg1}, arg2...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendTxAsBytes", reflect.TypeOf((*MockRingServiceClient)(nil).SendTxAsBytes), varargs...)
}
// SendTxAsEth mocks base method.
func (m *MockRingServiceClient) SendTxAsEth(arg0 context.Context, arg1 *basev1.TransactionEth, arg2 ...grpc.CallOption) (*ringv1.SendRawTransactionResponse, error) {
m.ctrl.T.Helper()
varargs := []interface{}{arg0, arg1}
for _, a := range arg2 {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "SendTxAsEth", varargs...)
ret0, _ := ret[0].(*ringv1.SendRawTransactionResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SendTxAsEth indicates an expected call of SendTxAsEth.
func (mr *MockRingServiceClientMockRecorder) SendTxAsEth(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]interface{}{arg0, arg1}, arg2...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendTxAsEth", reflect.TypeOf((*MockRingServiceClient)(nil).SendTxAsEth), varargs...)
}
// SendTxAsStd mocks base method.
func (m *MockRingServiceClient) SendTxAsStd(arg0 context.Context, arg1 *basev1.TransactionStd, arg2 ...grpc.CallOption) (*ringv1.SendRawTransactionResponse, error) {
m.ctrl.T.Helper()
varargs := []interface{}{arg0, arg1}
for _, a := range arg2 {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "SendTxAsStd", varargs...)
ret0, _ := ret[0].(*ringv1.SendRawTransactionResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SendTxAsStd indicates an expected call of SendTxAsStd.
func (mr *MockRingServiceClientMockRecorder) SendTxAsStd(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]interface{}{arg0, arg1}, arg2...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendTxAsStd", reflect.TypeOf((*MockRingServiceClient)(nil).SendTxAsStd), varargs...)
}
package benchmark_test
import (
"context"
"crypto/ecdsa"
"fmt"
"testing"
"time"
"math/big"
base "github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/base/v1"
ring "github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/ring/v1"
"github.com/ethereum/go-ethereum/crypto"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
//"google.golang.org/grpc/encoding/proto"
//"github.com/protocolbuffers/protobuf-go/proto"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/anypb"
)
var tableTx = []struct {
input int
}{
{input: 100},
{input: 200},
{input: 500},
{input: 1000},
{input: 2000},
{input: 5000},
{input: 10000},
{input: 20000},
// {input: 50000},
}
func RepeatedEthTx(txl int, b *testing.B) {
//b.Logf("b.N: %d\n", b.N)
local, err := crypto.HexToECDSA("FD5CC6F5E7E2805E920AC5DC83D5AF1106F9C92F0C04F9D5E1FD4261B4B4464A")
if err != nil {
b.Fatal(err)
}
publicKey := local.Public()
publicKeyECDSA, _ := publicKey.(*ecdsa.PublicKey)
fromAddr := crypto.PubkeyToAddress(*publicKeyECDSA)
remote, err := crypto.GenerateKey()
if err != nil {
b.Fatal(err)
}
tx, err := pricedTransaction(crypto.PubkeyToAddress(remote.PublicKey), 0, 100000, big.NewInt(1), local)
//txsQueue, err := ProduceOriginalTxByCount(500000)
if err != nil {
b.Fatal(err)
}
beginTime := time.Now()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
conn, err := grpc.Dial("127.0.0.1:9006", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
b.Fatal(err)
}
defer conn.Close()
c := ring.NewRingServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
txs := make([]*base.TransactionEth, 0, txl)
for i := 0; i < txl; i++ {
//tx := <-txsQueue
inner := base.EthTxData{
AccountNonce: tx.Nonce(),
Price: tx.GasPrice().Bytes(),
GasLimit: tx.Gas(),
Payload: tx.Data(),
}
v, r, sigs := tx.RawSignatureValues()
inner.V = v.Bytes()
inner.R = r.Bytes()
inner.S = sigs.Bytes()
inner.Amount = tx.Value().Bytes()
addr := base.Address{Address: tx.To().Bytes()}
inner.Recipient = &addr
inner.From = fromAddr.Bytes()
txs = append(txs, &base.TransactionEth{Tx: &base.EthTx{Inner: &inner}})
}
req := &base.RepeatedEthTx{Txs: txs}
out, err := proto.Marshal(req)
if err != nil {
b.Fatal(err)
}
b.SetBytes(int64(len(out)))
res, err := c.SendRepeatedEthTx(ctx, req)
if err != nil {
b.Fatal(err)
}
_ = res
// if bytes.Compare(tx.Hash().Bytes(), res.TxHash) != 0 {
// b.Fatal(err)
// }
// onceHash.Do(func() {
// b.Logf("response: %x local: %x \n", res.TxHash, tx.Hash().Bytes())
// })
}
})
b.ReportMetric(float64(b.N)/float64(time.Since(beginTime).Seconds()), "tps")
}
func RepeatedTxEthAsAny(txl int, b *testing.B) {
// onceFunc := func() {
local, _ := crypto.HexToECDSA("FD5CC6F5E7E2805E920AC5DC83D5AF1106F9C92F0C04F9D5E1FD4261B4B4464A")
publicKey := local.Public()
publicKeyECDSA, _ := publicKey.(*ecdsa.PublicKey)
fromAddr := crypto.PubkeyToAddress(*publicKeyECDSA)
remote, _ := crypto.GenerateKey()
var err error
tx, err := pricedTransaction(crypto.PubkeyToAddress(remote.PublicKey), 0, 100000, big.NewInt(1), local)
if err != nil {
b.Fatal(err)
}
//}
// once.Do(onceFunc)
beginTime := time.Now()
b.ResetTimer()
// The loop body is executed b.N times total across all goroutines.
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
conn, err := grpc.Dial("127.0.0.1:9006", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
b.Fatal(err)
}
defer conn.Close()
c := ring.NewRingServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
txs := make([]*base.TransactionEth, 0, txl)
for i := 0; i < txl; i++ {
inner := base.EthTxData{
AccountNonce: tx.Nonce(),
Price: tx.GasPrice().Bytes(),
GasLimit: tx.Gas(),
Payload: tx.Data(),
}
v, r, sigs := tx.RawSignatureValues()
inner.V = v.Bytes()
inner.R = r.Bytes()
inner.S = sigs.Bytes()
inner.Amount = tx.Value().Bytes()
addr := base.Address{Address: tx.To().Bytes()}
inner.Recipient = &addr
inner.From = fromAddr.Bytes()
txs = append(txs, &base.TransactionEth{Tx: &base.EthTx{Inner: &inner}})
}
ethTxAsAny, err := anypb.New(&base.RepeatedEthTx{Txs: txs})
if err != nil {
b.Fatal(err)
}
req := &base.Transaction{Tx: ethTxAsAny}
out, err := proto.Marshal(req)
if err != nil {
b.Fatal(err)
}
b.SetBytes(int64(len(out)))
res, err := c.SendTxAsAny(ctx, req)
if err != nil {
b.Fatal(err)
}
_ = res
// if bytes.Compare(tx.Hash().Bytes(), res.TxHash) != 0 {
// b.Fatal(err)
// }
// onceHash.Do(func() {
// b.Logf("response: %x local: %x \n", res.TxHash, tx.Hash().Bytes())
// })
}
})
b.ReportMetric(float64(b.N)/float64(time.Since(beginTime).Seconds()), "tps")
}
// go test -v -run BenchmarkAnyTxEth -bench BenchmarkRepeated -benchmem -count 5 | tee old.txt
// Small p-values indicate that the two distributions are significantly different.
// If the test indicates that there was no significant change between the two benchmarks (defined as p > 0.05),
// benchstat displays a single ~ instead of the percent change.
/*
benchstat -geomean -delta-test utest -html RepeatedEthTx.txt RepeatedTxEthAsAny.txt > utest.html
benchstat -geomean -delta-test ttest -html RepeatedEthTx.txt RepeatedTxEthAsAny.txt > ttest.html
benchstat -geomean -delta-test none -html RepeatedEthTx.txt RepeatedTxEthAsAny.txt > none.html
*/
func BenchmarkRepeated(b *testing.B) {
for _, v := range tableTx {
b.Run(fmt.Sprintf("input_size_%d", v.input), func(b *testing.B) {
//go test -v -run BenchmarkAnyTxEth -bench BenchmarkRepeated -benchmem -count 30 | tee RepeatedEthTx.txt
//RepeatedEthTx(v.input, b)
//go test -v -run BenchmarkAnyTxEth -bench BenchmarkRepeated -benchmem -count 30 | tee RepeatedTxEthAsAny.txt
RepeatedTxEthAsAny(v.input, b)
})
}
}
// 验证和 b.Run sub-benchmark的时间一致;
func Benchmark200RepeatedEthTx(b *testing.B) {
RepeatedEthTx(5000, b)
}
// func BenchmarkRepeatedNew(b *testing.B) {
// for _, v := range tableTx {
// b.Run(fmt.Sprintf("input_size_%d", v.input), func(b *testing.B) {
// RepeatedTxEthAsAny(v.input, b)
// })
// }
// }
package benchmark_test
import (
"bytes"
"context"
"crypto/ecdsa"
"encoding/gob"
"errors"
"fmt"
"time"
"unsafe"
"math/big"
"net"
"testing"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/anypb"
"google.golang.org/protobuf/types/known/emptypb"
base "github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/base/v1"
ring "github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/ring/v1"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
)
var countParallelAsEth int64
var countParallelAsStd int64
var countParallelAsAny int64
var countParallelAsBytes int64
type RingServer struct {
ring.UnimplementedRingServiceServer
}
func (*RingServer) SendRepeatedStdTx(context.Context, *base.RepeatedStdTx) (*ring.SendRawTransactionResponse, error) {
//fmt.Printf("SendEmptyMsg: %s \n", time.Now())
return &ring.SendRawTransactionResponse{}, nil
}
func (*RingServer) SendRepeatedEthTx(context.Context, *base.RepeatedEthTx) (*ring.SendRawTransactionResponse, error) {
//fmt.Printf("SendEmptyMsg: %s \n", time.Now())
return &ring.SendRawTransactionResponse{}, nil
}
func (*RingServer) SendEmptyMsg(context.Context, *ring.EmptyRequest) (*ring.EmptyResponse, error) {
//fmt.Printf("SendEmptyMsg: %s \n", time.Now())
return &ring.EmptyResponse{}, nil
}
func (*RingServer) SendEmpty(context.Context, *emptypb.Empty) (*emptypb.Empty, error) {
return &emptypb.Empty{}, nil
}
func (*RingServer) SendTxAsEth(ctx context.Context, in *base.TransactionEth) (*ring.SendRawTransactionResponse, error) {
addr := common.Address{}
copy(addr[:], in.Tx.Inner.Recipient.Address[:common.AddressLength])
ethTx := types.NewTx(&types.LegacyTx{
Nonce: in.Tx.Inner.AccountNonce,
To: &addr,
Value: new(big.Int).SetBytes(in.Tx.Inner.Amount),
Gas: in.Tx.Inner.GasLimit,
GasPrice: new(big.Int).SetBytes(in.Tx.Inner.Price),
Data: in.Tx.Inner.Payload,
V: new(big.Int).SetBytes(in.Tx.Inner.V),
R: new(big.Int).SetBytes(in.Tx.Inner.R),
S: new(big.Int).SetBytes(in.Tx.Inner.S),
})
// atomic.AddInt64(&countParallelAsEth, 1)
// defer fmt.Println("countParallelAsEth", countParallelAsEth)
return &ring.SendRawTransactionResponse{TxHash: ethTx.Hash().Bytes()}, nil
}
func (*RingServer) SendTxAsStd(ctx context.Context, in *base.TransactionStd) (*ring.SendRawTransactionResponse, error) {
addr := common.Address{}
copy(addr[:], in.Tx.Inner.Recipient.Address[:common.AddressLength])
ethTx := types.NewTx(&types.LegacyTx{
Nonce: in.Tx.Inner.AccountNonce,
To: &addr,
Value: new(big.Int).SetBytes(in.Tx.Inner.Amount),
Gas: in.Tx.Inner.GasLimit,
GasPrice: new(big.Int).SetBytes(in.Tx.Inner.Price),
Data: in.Tx.Inner.Payload,
V: new(big.Int).SetBytes(in.Tx.Inner.V),
R: new(big.Int).SetBytes(in.Tx.Inner.R),
S: new(big.Int).SetBytes(in.Tx.Inner.S),
})
// atomic.AddInt64(&countParallelAsStd, 1)
// defer fmt.Println("countParallelAsStd", countParallelAsStd)
return &ring.SendRawTransactionResponse{TxHash: ethTx.Hash().Bytes()}, nil
}
func (*RingServer) SendTxAsAny(ctx context.Context, in *base.Transaction) (*ring.SendRawTransactionResponse, error) {
msg, err := in.Tx.UnmarshalNew()
if err != nil {
return nil, err
}
// atomic.AddInt64(&countParallelAsAny, 1)
// defer fmt.Println("countParallelAsAny", countParallelAsAny)
switch m := msg.(type) {
case *base.EthTx:
addr := common.Address{}
copy(addr[:], m.Inner.Recipient.Address[:common.AddressLength])
ethTx := types.NewTx(&types.LegacyTx{
Nonce: m.Inner.AccountNonce,
To: &addr,
Value: new(big.Int).SetBytes(m.Inner.Amount),
Gas: m.Inner.GasLimit,
GasPrice: new(big.Int).SetBytes(m.Inner.Price),
Data: m.Inner.Payload,
V: new(big.Int).SetBytes(m.Inner.V),
R: new(big.Int).SetBytes(m.Inner.R),
S: new(big.Int).SetBytes(m.Inner.S),
})
return &ring.SendRawTransactionResponse{TxHash: ethTx.Hash().Bytes()}, nil
case *base.StdTx:
addr := common.Address{}
copy(addr[:], m.Inner.Recipient.Address[:common.AddressLength])
ethTx := types.NewTx(&types.LegacyTx{
Nonce: m.Inner.AccountNonce,
To: &addr,
Value: new(big.Int).SetBytes(m.Inner.Amount),
Gas: m.Inner.GasLimit,
GasPrice: new(big.Int).SetBytes(m.Inner.Price),
Data: m.Inner.Payload,
V: new(big.Int).SetBytes(m.Inner.V),
R: new(big.Int).SetBytes(m.Inner.R),
S: new(big.Int).SetBytes(m.Inner.S),
})
return &ring.SendRawTransactionResponse{TxHash: ethTx.Hash().Bytes()}, nil
case *base.RepeatedEthTx:
return &ring.SendRawTransactionResponse{}, nil
default:
return nil, errors.New(fmt.Sprintf("server expected tx type: %T and %T, but actually is %T", base.EthTx{}, base.StdTx{}, msg))
}
}
func (*RingServer) SendTxAsBytes(ctx context.Context, in *base.TransactionBytes) (*ring.SendRawTransactionResponse, error) {
ethTx := types.Transaction{}
if err := ethTx.UnmarshalBinary(in.Tx); err != nil {
return nil, err
}
// atomic.AddInt64(&countParallelAsBytes, 1)
// defer fmt.Printf("countParallelAsBytes: %d\n", countParallelAsBytes)
return &ring.SendRawTransactionResponse{TxHash: ethTx.Hash().Bytes()}, nil
}
func TestGrpcServer(t *testing.T) {
lis, err := net.Listen("tcp", ":9006")
if err != nil {
t.Fatal(err)
}
s := grpc.NewServer()
ring.RegisterRingServiceServer(s, &RingServer{})
err = s.Serve(lis)
if err != nil {
t.Fatal(err)
}
}
func TestType(t *testing.T) {
ethTx := base.EthTx{}
fmt.Println(ethTx.ProtoReflect().Descriptor().FullName())
}
func TestAnyTx(t *testing.T) {
local, _ := crypto.HexToECDSA("FD5CC6F5E7E2805E920AC5DC83D5AF1106F9C92F0C04F9D5E1FD4261B4B4464A")
publicKey := local.Public()
publicKeyECDSA, _ := publicKey.(*ecdsa.PublicKey)
fromAddr := crypto.PubkeyToAddress(*publicKeyECDSA)
remote, _ := crypto.GenerateKey()
tx, err := pricedTransaction(crypto.PubkeyToAddress(remote.PublicKey), 0, 100000, big.NewInt(1), local)
if err != nil {
t.Fatal(err)
}
conn, err := grpc.Dial("127.0.0.1:9006", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
t.Fatal(err)
}
defer conn.Close()
c := ring.NewRingServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
_, _ = c, ctx
inner := base.EthTxData{
AccountNonce: tx.Nonce(),
Price: tx.GasPrice().Bytes(),
GasLimit: tx.Gas(),
Payload: tx.Data(),
}
v, r, sigs := tx.RawSignatureValues()
inner.V = v.Bytes()
inner.R = r.Bytes()
inner.S = sigs.Bytes()
inner.Amount = tx.Value().Bytes()
addr := base.Address{Address: tx.To().Bytes()}
inner.Recipient = &addr
inner.From = fromAddr.Bytes()
ethTx := base.EthTx{Inner: &inner}
ethTxAsAny, err := anypb.New(&ethTx)
if err != nil {
t.Fatal(err)
}
//fmt.Println("ethTxAsAny.ProtoReflect().Descriptor().FullName()", ethTx.ProtoReflect().Descriptor().FullName())
res, err := c.SendTxAsAny(ctx, &base.Transaction{Tx: ethTxAsAny})
_ = res
if err != nil {
t.Fatal(err)
}
stdInner := base.StdTxData{
AccountNonce: tx.Nonce(),
Price: tx.GasPrice().Bytes(),
GasLimit: tx.Gas(),
Payload: tx.Data(),
}
// v, r, sigs := tx.RawSignatureValues()
stdInner.V = v.Bytes()
stdInner.R = r.Bytes()
stdInner.S = sigs.Bytes()
stdInner.Amount = tx.Value().Bytes()
//addr := base.Address{Address: tx.To().Bytes()}
stdInner.Recipient = &addr
stdTx := base.StdTx{Inner: &stdInner}
_ = stdTx
stdTxAsAny, err := anypb.New(&stdTx)
if err != nil {
t.Fatal(err)
}
_ = stdTxAsAny
res, err = c.SendTxAsAny(ctx, &base.Transaction{Tx: stdTxAsAny})
if err != nil {
t.Fatal(err)
}
_ = res
}
func TestSizeOf(t *testing.T) {
local, _ := crypto.HexToECDSA("FD5CC6F5E7E2805E920AC5DC83D5AF1106F9C92F0C04F9D5E1FD4261B4B4464A")
publicKey := local.Public()
publicKeyECDSA, _ := publicKey.(*ecdsa.PublicKey)
fromAddr := crypto.PubkeyToAddress(*publicKeyECDSA)
remote, _ := crypto.GenerateKey()
tx, err := pricedTransaction(crypto.PubkeyToAddress(remote.PublicKey), 0, 100000, big.NewInt(1), local)
if err != nil {
t.Fatal(err)
}
inner := base.EthTxData{
AccountNonce: tx.Nonce(),
Price: tx.GasPrice().Bytes(),
GasLimit: tx.Gas(),
Payload: tx.Data(),
}
v, r, sigs := tx.RawSignatureValues()
inner.V = v.Bytes()
inner.R = r.Bytes()
inner.S = sigs.Bytes()
inner.Amount = tx.Value().Bytes()
addr := base.Address{Address: tx.To().Bytes()}
inner.Recipient = &addr
inner.From = fromAddr.Bytes()
out, err := proto.Marshal(&base.TransactionEth{Tx: &base.EthTx{Inner: &inner}})
if err != nil {
t.Fatal(err)
}
fmt.Printf("TransactionEth proto buff encoding: %d \n", len(out))
//fmt.Printf("%T \n", unsafe.Sizeof(tx.Nonce()))
sss, err := getRealSizeOf(tx)
if err != nil {
t.Fatal(err)
}
fmt.Println("getRealSizeOf tx ", sss)
ssss, err := getRealSizeOf(base.TransactionEth{Tx: &base.EthTx{Inner: &inner}})
if err != nil {
t.Fatal(err)
}
fmt.Println("getRealSizeOf TransactionEth", ssss)
fmt.Println("unsafe.Sizeof", unsafe.Sizeof(*tx))
fmt.Println("unsafe.Sizeof v", unsafe.Sizeof(*v))
fmt.Println("unsafe.Sizeof r", unsafe.Sizeof(*r))
fmt.Println("unsafe.Sizeof sigs", unsafe.Sizeof(*sigs))
fmt.Println("tx size", tx.Size())
// v, r, sigs
}
// type ASDF struct {
// A uint64
// B uint64
// C uint64
// D uint64
// E uint64
// F string
// }
// func (s *ASDF) size() int {
// size := int(unsafe.Sizeof(*s))
// size += len(s.F)
// return size
// }
func getRealSizeOf(v interface{}) (int, error) {
b := new(bytes.Buffer)
if err := gob.NewEncoder(b).Encode(v); err != nil {
return 0, err
}
return b.Len(), nil
}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Performance Result Comparison</title>
<style>
.benchstat { border-collapse: collapse; }
.benchstat th:nth-child(1) { text-align: left; }
.benchstat tbody td:nth-child(1n+2):not(.note) { text-align: right; padding: 0em 1em; }
.benchstat tr:not(.configs) th { border-top: 1px solid #666; border-bottom: 1px solid #ccc; }
.benchstat .nodelta { text-align: center !important; }
.benchstat .better td.delta { font-weight: bold; }
.benchstat .worse td.delta { font-weight: bold; color: #c00; }
</style>
</head>
<body>
<table class='benchstat oldnew'>
<tr class='configs'><th><th>RepeatedEthTx.txt<th>RepeatedTxEthAsAny.txt
<tbody>
<tr><th><th colspan='2' class='metric'>time/op<th>delta
<tr class='worse'><td>Repeated/input_size_100-8<td>211µs ± 4%<td>214µs ± 5%<td class='delta'>+1.35%<td class='note'>(p=0.011 n=30+30)
<tr class='unchanged'><td>Repeated/input_size_200-8<td>284µs ± 3%<td>284µs ± 4%<td class='nodelta'>~<td class='note'>(p=0.731 n=30+29)
<tr class='unchanged'><td>Repeated/input_size_500-8<td>521µs ± 3%<td>524µs ± 4%<td class='nodelta'>~<td class='note'>(p=0.231 n=30+30)
<tr class='worse'><td>Repeated/input_size_1000-8<td>1.00ms ±11%<td>1.04ms ± 4%<td class='delta'>+3.93%<td class='note'>(p=0.002 n=30+24)
<tr class='worse'><td>Repeated/input_size_2000-8<td>1.78ms ±14%<td>1.95ms ± 2%<td class='delta'>+9.25%<td class='note'>(p=0.000 n=30+30)
<tr class='worse'><td>Repeated/input_size_5000-8<td>3.99ms ± 3%<td>4.58ms ± 2%<td class='delta'>+14.91%<td class='note'>(p=0.000 n=30+27)
<tr class='worse'><td>Repeated/input_size_10000-8<td>7.72ms ± 2%<td>8.86ms ± 3%<td class='delta'>+14.69%<td class='note'>(p=0.000 n=29+30)
<tr class='worse'><td>Repeated/input_size_20000-8<td>14.9ms ± 4%<td>17.0ms ± 2%<td class='delta'>+13.45%<td class='note'>(p=0.000 n=23+30)
<tr class='unchanged'><td>[Geo mean]<td>1.50ms <td>1.61ms <td class='delta'>+7.10%<td class='note'>
<tr><td>&nbsp;
</tbody>
<tbody>
<tr><th><th colspan='2' class='metric'>speed<th>delta
<tr class='worse'><td>Repeated/input_size_100-8<td>64.2MB/s ± 4%<td>63.3MB/s ± 5%<td class='delta'>−1.31%<td class='note'>(p=0.012 n=30+30)
<tr class='unchanged'><td>Repeated/input_size_200-8<td>95.3MB/s ± 3%<td>95.2MB/s ± 4%<td class='nodelta'>~<td class='note'>(p=0.740 n=30+29)
<tr class='unchanged'><td>Repeated/input_size_500-8<td>130MB/s ± 3%<td>129MB/s ± 3%<td class='nodelta'>~<td class='note'>(p=0.260 n=30+30)
<tr class='worse'><td>Repeated/input_size_1000-8<td>136MB/s ±12%<td>130MB/s ± 4%<td class='delta'>−4.15%<td class='note'>(p=0.002 n=30+24)
<tr class='worse'><td>Repeated/input_size_2000-8<td>153MB/s ±13%<td>139MB/s ± 2%<td class='delta'>−8.97%<td class='note'>(p=0.000 n=30+30)
<tr class='worse'><td>Repeated/input_size_5000-8<td>169MB/s ± 2%<td>147MB/s ± 3%<td class='delta'>−13.15%<td class='note'>(p=0.000 n=30+27)
<tr class='worse'><td>Repeated/input_size_10000-8<td>175MB/s ± 4%<td>152MB/s ± 3%<td class='delta'>−12.70%<td class='note'>(p=0.000 n=30+30)
<tr class='worse'><td>Repeated/input_size_20000-8<td>179MB/s ±10%<td>159MB/s ± 2%<td class='delta'>−11.06%<td class='note'>(p=0.000 n=25+30)
<tr class='unchanged'><td>[Geo mean]<td>131MB/s <td>122MB/s <td class='delta'>−6.64%<td class='note'>
<tr><td>&nbsp;
</tbody>
<tbody>
<tr><th><th colspan='2' class='metric'>tps<th>delta
<tr class='better'><td>Repeated/input_size_100-8<td>4.74k ± 4%<td>4.68k ± 5%<td class='delta'>−1.32%<td class='note'>(p=0.012 n=30+30)
<tr class='unchanged'><td>Repeated/input_size_200-8<td>3.52k ± 3%<td>3.52k ± 4%<td class='nodelta'>~<td class='note'>(p=0.732 n=30+29)
<tr class='unchanged'><td>Repeated/input_size_500-8<td>1.92k ± 3%<td>1.91k ± 3%<td class='nodelta'>~<td class='note'>(p=0.227 n=30+30)
<tr class='better'><td>Repeated/input_size_1000-8<td>1.00k ±12%<td>0.96k ± 4%<td class='delta'>−4.15%<td class='note'>(p=0.002 n=30+24)
<tr class='better'><td>Repeated/input_size_2000-8<td>565 ±13%<td>514 ± 2%<td class='delta'>−8.97%<td class='note'>(p=0.000 n=30+30)
<tr class='better'><td>Repeated/input_size_5000-8<td>251 ± 2%<td>218 ± 3%<td class='delta'>−13.15%<td class='note'>(p=0.000 n=30+27)
<tr class='better'><td>Repeated/input_size_10000-8<td>129 ± 4%<td>113 ± 3%<td class='delta'>−12.69%<td class='note'>(p=0.000 n=30+30)
<tr class='better'><td>Repeated/input_size_20000-8<td>66.4 ±10%<td>59.0 ± 2%<td class='delta'>−11.09%<td class='note'>(p=0.000 n=25+30)
<tr class='unchanged'><td>[Geo mean]<td>667 <td>623 <td class='delta'>−6.64%<td class='note'>
<tr><td>&nbsp;
</tbody>
<tbody>
<tr><th><th colspan='2' class='metric'>alloc/op<th>delta
<tr class='unchanged'><td>Repeated/input_size_100-8<td>254kB ± 0%<td>254kB ± 0%<td class='nodelta'>~<td class='note'>(p=0.361 n=23+24)
<tr class='unchanged'><td>Repeated/input_size_200-8<td>365kB ± 0%<td>365kB ± 0%<td class='nodelta'>~<td class='note'>(p=0.679 n=29+28)
<tr class='unchanged'><td>Repeated/input_size_500-8<td>702kB ± 0%<td>702kB ± 0%<td class='nodelta'>~<td class='note'>(p=0.124 n=30+30)
<tr class='unchanged'><td>Repeated/input_size_1000-8<td>1.23MB ± 0%<td>1.23MB ± 0%<td class='nodelta'>~<td class='note'>(p=0.121 n=29+30)
<tr class='unchanged'><td>Repeated/input_size_2000-8<td>2.28MB ± 0%<td>2.28MB ± 0%<td class='nodelta'>~<td class='note'>(p=0.626 n=30+30)
<tr class='worse'><td>Repeated/input_size_5000-8<td>5.48MB ± 0%<td>5.48MB ± 0%<td class='delta'>+0.00%<td class='note'>(p=0.010 n=30+28)
<tr class='unchanged'><td>Repeated/input_size_10000-8<td>10.8MB ± 0%<td>10.8MB ± 0%<td class='nodelta'>~<td class='note'>(p=0.262 n=30+29)
<tr class='unchanged'><td>Repeated/input_size_20000-8<td>21.4MB ± 0%<td>21.4MB ± 0%<td class='nodelta'>~<td class='note'>(p=0.604 n=29+27)
<tr class='unchanged'><td>[Geo mean]<td>1.97MB <td>1.97MB <td class='delta'>+0.00%<td class='note'>
<tr><td>&nbsp;
</tbody>
<tbody>
<tr><th><th colspan='2' class='metric'>allocs/op<th>delta
<tr class='unchanged'><td>Repeated/input_size_100-8<td>2.12k ± 0%<td>2.12k ± 0%<td class='nodelta'>~<td class='note'>(zero variance)
<tr class='unchanged'><td>Repeated/input_size_200-8<td>3.62k ± 0%<td>3.62k ± 0%<td class='nodelta'>~<td class='note'>(zero variance)
<tr class='unchanged'><td>Repeated/input_size_500-8<td>8.14k ± 0%<td>8.14k ± 0%<td class='nodelta'>~<td class='note'>(zero variance)
<tr class='unchanged'><td>Repeated/input_size_1000-8<td>15.6k ± 0%<td>15.6k ± 0%<td class='nodelta'>~<td class='note'>(p=0.092 n=30+30)
<tr class='unchanged'><td>Repeated/input_size_2000-8<td>30.7k ± 0%<td>30.7k ± 0%<td class='nodelta'>~<td class='note'>(p=0.623 n=30+30)
<tr class='worse'><td>Repeated/input_size_5000-8<td>75.7k ± 0%<td>75.7k ± 0%<td class='delta'>+0.00%<td class='note'>(p=0.000 n=29+29)
<tr class='unchanged'><td>Repeated/input_size_10000-8<td>151k ± 0%<td>151k ± 0%<td class='nodelta'>~<td class='note'>(p=0.072 n=30+30)
<tr class='worse'><td>Repeated/input_size_20000-8<td>301k ± 0%<td>301k ± 0%<td class='delta'>+0.00%<td class='note'>(p=0.017 n=29+28)
<tr class='unchanged'><td>[Geo mean]<td>23.8k <td>23.8k <td class='delta'>+0.00%<td class='note'>
<tr><td>&nbsp;
</tbody>
</table>
</body>
</html>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Performance Result Comparison</title>
<style>
.benchstat { border-collapse: collapse; }
.benchstat th:nth-child(1) { text-align: left; }
.benchstat tbody td:nth-child(1n+2):not(.note) { text-align: right; padding: 0em 1em; }
.benchstat tr:not(.configs) th { border-top: 1px solid #666; border-bottom: 1px solid #ccc; }
.benchstat .nodelta { text-align: center !important; }
.benchstat .better td.delta { font-weight: bold; }
.benchstat .worse td.delta { font-weight: bold; color: #c00; }
</style>
</head>
<body>
<table class='benchstat oldnew'>
<tr class='configs'><th><th>RepeatedEthTx.txt<th>RepeatedTxEthAsAny.txt
<tbody>
<tr><th><th colspan='2' class='metric'>time/op<th>delta
<tr class='worse'><td>Repeated/input_size_100-8<td>211µs ± 4%<td>214µs ± 5%<td class='delta'>+1.35%<td class='note'>(p=0.020 n=30+30)
<tr class='unchanged'><td>Repeated/input_size_200-8<td>284µs ± 3%<td>284µs ± 4%<td class='nodelta'>~<td class='note'>(p=0.874 n=30+29)
<tr class='unchanged'><td>Repeated/input_size_500-8<td>521µs ± 3%<td>524µs ± 4%<td class='nodelta'>~<td class='note'>(p=0.279 n=30+30)
<tr class='worse'><td>Repeated/input_size_1000-8<td>1.00ms ±11%<td>1.04ms ± 4%<td class='delta'>+3.93%<td class='note'>(p=0.024 n=30+24)
<tr class='worse'><td>Repeated/input_size_2000-8<td>1.78ms ±14%<td>1.95ms ± 2%<td class='delta'>+9.25%<td class='note'>(p=0.000 n=30+30)
<tr class='worse'><td>Repeated/input_size_5000-8<td>3.99ms ± 3%<td>4.58ms ± 2%<td class='delta'>+14.91%<td class='note'>(p=0.000 n=30+27)
<tr class='worse'><td>Repeated/input_size_10000-8<td>7.72ms ± 2%<td>8.86ms ± 3%<td class='delta'>+14.69%<td class='note'>(p=0.000 n=29+30)
<tr class='worse'><td>Repeated/input_size_20000-8<td>14.9ms ± 4%<td>17.0ms ± 2%<td class='delta'>+13.45%<td class='note'>(p=0.000 n=23+30)
<tr class='unchanged'><td>[Geo mean]<td>1.50ms <td>1.61ms <td class='delta'>+7.10%<td class='note'>
<tr><td>&nbsp;
</tbody>
<tbody>
<tr><th><th colspan='2' class='metric'>speed<th>delta
<tr class='worse'><td>Repeated/input_size_100-8<td>64.2MB/s ± 4%<td>63.3MB/s ± 5%<td class='delta'>−1.31%<td class='note'>(p=0.021 n=30+30)
<tr class='unchanged'><td>Repeated/input_size_200-8<td>95.3MB/s ± 3%<td>95.2MB/s ± 4%<td class='nodelta'>~<td class='note'>(p=0.874 n=30+29)
<tr class='unchanged'><td>Repeated/input_size_500-8<td>130MB/s ± 3%<td>129MB/s ± 3%<td class='nodelta'>~<td class='note'>(p=0.280 n=30+30)
<tr class='worse'><td>Repeated/input_size_1000-8<td>136MB/s ±12%<td>130MB/s ± 4%<td class='delta'>−4.15%<td class='note'>(p=0.026 n=30+24)
<tr class='worse'><td>Repeated/input_size_2000-8<td>153MB/s ±13%<td>139MB/s ± 2%<td class='delta'>−8.97%<td class='note'>(p=0.000 n=30+30)
<tr class='worse'><td>Repeated/input_size_5000-8<td>169MB/s ± 2%<td>147MB/s ± 3%<td class='delta'>−13.15%<td class='note'>(p=0.000 n=30+27)
<tr class='worse'><td>Repeated/input_size_10000-8<td>175MB/s ± 4%<td>152MB/s ± 3%<td class='delta'>−12.70%<td class='note'>(p=0.000 n=30+30)
<tr class='worse'><td>Repeated/input_size_20000-8<td>179MB/s ±10%<td>159MB/s ± 2%<td class='delta'>−11.06%<td class='note'>(p=0.000 n=25+30)
<tr class='unchanged'><td>[Geo mean]<td>131MB/s <td>122MB/s <td class='delta'>−6.64%<td class='note'>
<tr><td>&nbsp;
</tbody>
<tbody>
<tr><th><th colspan='2' class='metric'>tps<th>delta
<tr class='better'><td>Repeated/input_size_100-8<td>4.74k ± 4%<td>4.68k ± 5%<td class='delta'>−1.32%<td class='note'>(p=0.021 n=30+30)
<tr class='unchanged'><td>Repeated/input_size_200-8<td>3.52k ± 3%<td>3.52k ± 4%<td class='nodelta'>~<td class='note'>(p=0.879 n=30+29)
<tr class='unchanged'><td>Repeated/input_size_500-8<td>1.92k ± 3%<td>1.91k ± 3%<td class='nodelta'>~<td class='note'>(p=0.274 n=30+30)
<tr class='better'><td>Repeated/input_size_1000-8<td>1.00k ±12%<td>0.96k ± 4%<td class='delta'>−4.15%<td class='note'>(p=0.026 n=30+24)
<tr class='better'><td>Repeated/input_size_2000-8<td>565 ±13%<td>514 ± 2%<td class='delta'>−8.97%<td class='note'>(p=0.000 n=30+30)
<tr class='better'><td>Repeated/input_size_5000-8<td>251 ± 2%<td>218 ± 3%<td class='delta'>−13.15%<td class='note'>(p=0.000 n=30+27)
<tr class='better'><td>Repeated/input_size_10000-8<td>129 ± 4%<td>113 ± 3%<td class='delta'>−12.69%<td class='note'>(p=0.000 n=30+30)
<tr class='better'><td>Repeated/input_size_20000-8<td>66.4 ±10%<td>59.0 ± 2%<td class='delta'>−11.09%<td class='note'>(p=0.000 n=25+30)
<tr class='unchanged'><td>[Geo mean]<td>667 <td>623 <td class='delta'>−6.64%<td class='note'>
<tr><td>&nbsp;
</tbody>
<tbody>
<tr><th><th colspan='2' class='metric'>alloc/op<th>delta
<tr class='unchanged'><td>Repeated/input_size_100-8<td>254kB ± 0%<td>254kB ± 0%<td class='nodelta'>~<td class='note'>(p=0.371 n=23+24)
<tr class='unchanged'><td>Repeated/input_size_200-8<td>365kB ± 0%<td>365kB ± 0%<td class='nodelta'>~<td class='note'>(p=0.643 n=29+28)
<tr class='unchanged'><td>Repeated/input_size_500-8<td>702kB ± 0%<td>702kB ± 0%<td class='nodelta'>~<td class='note'>(p=0.113 n=30+30)
<tr class='unchanged'><td>Repeated/input_size_1000-8<td>1.23MB ± 0%<td>1.23MB ± 0%<td class='nodelta'>~<td class='note'>(p=0.234 n=29+30)
<tr class='unchanged'><td>Repeated/input_size_2000-8<td>2.28MB ± 0%<td>2.28MB ± 0%<td class='nodelta'>~<td class='note'>(p=0.813 n=30+30)
<tr class='worse'><td>Repeated/input_size_5000-8<td>5.48MB ± 0%<td>5.48MB ± 0%<td class='delta'>+0.00%<td class='note'>(p=0.015 n=30+28)
<tr class='unchanged'><td>Repeated/input_size_10000-8<td>10.8MB ± 0%<td>10.8MB ± 0%<td class='nodelta'>~<td class='note'>(p=0.285 n=30+29)
<tr class='unchanged'><td>Repeated/input_size_20000-8<td>21.4MB ± 0%<td>21.4MB ± 0%<td class='nodelta'>~<td class='note'>(p=0.605 n=29+27)
<tr class='unchanged'><td>[Geo mean]<td>1.97MB <td>1.97MB <td class='delta'>+0.00%<td class='note'>
<tr><td>&nbsp;
</tbody>
<tbody>
<tr><th><th colspan='2' class='metric'>allocs/op<th>delta
<tr class='unchanged'><td>Repeated/input_size_100-8<td>2.12k ± 0%<td>2.12k ± 0%<td class='nodelta'>~<td class='note'>(all equal)
<tr class='unchanged'><td>Repeated/input_size_200-8<td>3.62k ± 0%<td>3.62k ± 0%<td class='nodelta'>~<td class='note'>(all equal)
<tr class='unchanged'><td>Repeated/input_size_500-8<td>8.14k ± 0%<td>8.14k ± 0%<td class='nodelta'>~<td class='note'>(all equal)
<tr class='unchanged'><td>Repeated/input_size_1000-8<td>15.6k ± 0%<td>15.6k ± 0%<td class='nodelta'>~<td class='note'>(p=0.106 n=30+30)
<tr class='unchanged'><td>Repeated/input_size_2000-8<td>30.7k ± 0%<td>30.7k ± 0%<td class='nodelta'>~<td class='note'>(p=0.728 n=30+30)
<tr class='worse'><td>Repeated/input_size_5000-8<td>75.7k ± 0%<td>75.7k ± 0%<td class='delta'>+0.00%<td class='note'>(p=0.000 n=29+29)
<tr class='unchanged'><td>Repeated/input_size_10000-8<td>151k ± 0%<td>151k ± 0%<td class='nodelta'>~<td class='note'>(p=0.087 n=30+30)
<tr class='worse'><td>Repeated/input_size_20000-8<td>301k ± 0%<td>301k ± 0%<td class='delta'>+0.00%<td class='note'>(p=0.019 n=29+28)
<tr class='unchanged'><td>[Geo mean]<td>23.8k <td>23.8k <td class='delta'>+0.00%<td class='note'>
<tr><td>&nbsp;
</tbody>
</table>
</body>
</html>
version: v1
managed:
enabled: true
go_package_prefix:
default: github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go
except:
- buf.build/gogo/protobuf
# - buf.build/googleapis/googleapis
plugins:
- name: gogo
out: gen/proto/go
opt:
- paths=source_relative
- Mgoogle/protobuf/any.proto=github.com/gogo/protobuf/types
- Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types
- Mgoogle/protobuf=github.com/gogo/protobuf/types
- name: go-grpc
out: gen/proto/go
opt: paths=source_relative
- name: grpc-gateway
out: gen/proto/go
opt: paths=source_relative
\ No newline at end of file
version: v1
directories:
- baseapi
- crypterapi
- ethrpcapi
- nebulaapi
- p2papi
- ringapi
- sentryapi
#- txcheckerapi
\ No newline at end of file
# Generated by buf. DO NOT EDIT.
version: v1
version: v1
breaking:
use:
- FILE
lint:
use:
- DEFAULT
syntax = "proto3";
package crypter.v1;
import "google/protobuf/field_mask.proto";
import "google/protobuf/timestamp.proto";
import "base/v1/meta.proto";
import "crypter/v1/resource.proto";
message BatchSignRequest {
repeated bytes privk = 1;
repeated bytes data = 2;
CryptType crypt_type = 3;
}
message BatchSignResponse {
repeated bytes signature = 1;
}
message BatchVerifyRequest {
repeated bytes pubkey = 1;
repeated bytes signature = 2;
CryptType crypt_type = 3;
}
message BatchVerifyResponse {
repeated bool verified = 1;
}
message BatchRecoverRequest {
repeated bytes data = 1;
repeated bytes signature = 2;
CryptType crypt_type = 3;
}
message BatchRecoverResponse {
repeated bytes pubkey = 1;
}
message BatchRecoverTxRequest {
repeated base.v1.MetaTxBase raw_tx = 1;
}
message BatchRecoverTxResponse {
repeated base.v1.MetaTxBase recoverd_tx = 1;
}
syntax = "proto3";
package crypter.v1;
enum CryptType {
CRYPT_TYPE_INVALID = 0;
CRYPT_TYPE_SECP256K1 = 1;
}
\ No newline at end of file
syntax = "proto3";
package crypter.v1;
import "crypter/v1/request_response.proto";
service CrypterService {
rpc BatchSign(BatchSignRequest) returns (BatchSignResponse) {}
rpc BatchVerify(BatchVerifyRequest) returns (BatchVerifyResponse) {}
rpc BatchRecover(BatchRecoverRequest) returns (BatchRecoverResponse) {}
rpc BatchRecoverTx(BatchRecoverTxRequest) returns (BatchRecoverTxResponse) {}
}
recover from is used in ring module, if recover failed, the from will return with 0x00...00
# Generated by buf. DO NOT EDIT.
version: v1
version: v1
breaking:
use:
- FILE
lint:
use:
- DEFAULT
syntax = "proto3";
package ethrpc.v1;
import "google/protobuf/field_mask.proto";
import "google/protobuf/timestamp.proto";
import "ethrpc/v1/resource.proto";
message NodeVersionRequest { }
message NodeVersionResponse {
bytes version = 1;
}
message Sha3Request {
// data need to caculate sha3.
bytes data = 1;
}
message Sha3Response {
//
bytes hash = 1;
}
message NetVersionRequest { }
message NetVersionResponse {
bytes version = 1;
}
message NetPeerCountRequest { }
message NetPeerCountResponse {
uint32 peer_count = 1;
}
message ProtocolVersionRequest { }
message ProtocolVersionResponse {
bytes version = 1;
}
message SyncingRequest { }
message SyncingResponse {
bytes start = 1;
bytes end = 2;
bytes current = 3;
}
message CoinbaseRequest { }
message CoinbaseResponse {
bytes address = 1;
}
message MiningRequest { }
message MiningResponse {
string status = 1;
}
message HashRateRequest { }
message HashRateResponse {
string result = 1;
}
message GasPriceRequest { }
message GasPriceResponse {
// gas price in wei.
bytes gas_price = 1;
}
message AccountsRequest { }
message AccountsResponse {
repeated bytes address = 1;
}
message HeightRequest { }
message HeightResponse {
bytes height = 1;
}
message BalanceRequest {
// request address
bytes address = 1;
// request block number
bytes block_id = 2;
}
message BalanceResponse {
// the address
bytes address = 1;
// block height
bytes block_id = 2;
// balance
bytes balance = 3;
}
message StorageRequest {
bytes address = 1;
bytes block_id = 2;
bytes position = 3;
}
message StorageResponse {
bytes address = 1;
bytes block_id = 2;
bytes position = 3;
bytes data = 4;
}
message NonceRequest {
// request address
bytes address = 1;
// request block number
bytes block_id = 2;
}
message NonceResponse {
// the address
bytes address = 1;
// block height
bytes block_id = 2;
// nonce
bytes nonce = 3;
}
message RepeatedNonceRequest {
// request address
repeated bytes address = 1;
// request block number
repeated bytes block_id = 2;
}
message RepeatedNonceResponse {
// the address
repeated bytes address = 1;
// block height
repeated bytes block_id = 2;
// nonce
repeated bytes nonce = 3;
}
message TransactionCountRequest {
// request address
bytes address = 1;
// request block number
bytes block_id = 2;
}
message TransactionCountResponse {
// the address
bytes address = 1;
// block height
bytes block_id = 2;
// count
bytes count = 3;
}
message BlockTransactionCountByHashRequest {
bytes block_hash = 1;
}
message BlockTransactionCountByHashResponse {
bytes block_hash = 1;
uint32 count = 2;
}
message BlockTransactionCountByNumberRequest {
bytes block_id = 1;
}
message BlockTransactionCountByNumberResponse {
bytes block_id = 1;
uint32 count = 2;
}
message UncleCountByHashRequest {
bytes block_hash = 1;
}
message UncleCountByHashResponse {
bytes block_hash = 1;
uint32 count = 2;
}
message UncleCountByNumberRequest {
bytes block_id = 1;
}
message UncleCountByNumberResponse {
bytes block_id = 1;
uint32 count = 2;
}
message GetCodeRequest {
bytes address = 1;
bytes block_id = 2;
}
message GetCodeResponse {
bytes address = 1;
bytes block_id = 2;
bytes code = 3;
}
message SignRequest {
bytes address = 1;
bytes data = 2;
}
message SignResponse {
bytes signature = 1;
}
message SignTransactionRequest {
bytes address = 1;
bytes tx_data = 2;
bytes method = 3;
}
message SignTransactionResponse {
bytes signed_tx = 1;
}
message SendTransactionRequest {
bytes address = 1;
bytes tx_data = 2;
}
message SendTransactionResponse {
bytes tx_hash = 1;
}
message SendRawTransactionRequest {
bytes signed_tx = 1;
}
message SendRawTransactionResponse {
bytes tx_hash = 1;
}
message CallRequest {
bytes signed_tx = 1;
}
message CallResponse {
bytes result = 1;
}
message EstimateGasRequest {
bytes signed_tx = 1;
}
message EstimateGasResponse {
bytes result = 1;
uint32 gas = 2;
}
message BlockByHashRequest {
bytes block_hash = 1;
}
message BlockByHashResponse {
bytes block = 1;
}
message BlockByNumberRequest {
bytes block_id = 1;
}
message BlockByNumberResponse {
bytes block = 1;
}
message TransactionByHashRequest {
bytes tx_hash = 1;
}
message TransactionByHashResponse {
bytes tx_data = 1;
}
message TransactionByBlockHashAndIndexRequest {
bytes block_hash = 1;
uint32 index = 2;
}
message TransactionByBlockHashAndIndexResponse {
bytes tx_data = 1;
}
message TransactionByBlockNumberAndIndexRequest {
bytes block_id = 1;
uint32 index = 2;
}
message TransactionByBlockNumberAndIndexResponse {
bytes tx_data = 1;
}
message TransactionReceiptRequest {
bytes tx_hash = 1;
}
message TransactionReceiptResponse {
bytes tx_receipt = 1;
}
message UncleByBlockHashAndIndexRequest {
bytes block_hash = 1;
uint32 index = 2;
}
message UncleByBlockHashAndIndexResponse {
bytes uncle_block = 1;
}
message UncleByBlockNumberAndIndexRequest {
bytes block_id = 1;
uint32 index = 2;
}
message UncleByBlockNumberAndIndexResponse {
bytes uncle_block = 1;
}
message CompilersRequest {
}
message CompilersResponse {
bytes compilers = 1;
}
message CompileSolidityRequest {
bytes source = 1;
}
message CompileSolidityResponse {
bytes code = 1;
}
message CompileLLLRequest {
bytes source = 1;
}
message CompileLLLResponse {
bytes code = 1;
}
message CompileSerpentRequest {
bytes source = 1;
}
message CompileSerpentResponse {
bytes code = 1;
}
message NewFilterRequest {
bytes param = 1;
}
message NewFilterResponse {
bytes filter_id = 1;
}
message NewBlockFilterRequest { }
message NewBlockFilterResponse {
bytes filter_id = 1;
}
message PendingTransactionFilterRequest { }
message PendingTransactionFilterResponse {
bytes filter_id = 1;
}
message UninstallFilterRequest {
bytes filter_id = 1;
}
message UninstallFilterResponse {
bool result = 1;
}
message FilterChangesRequest {
bytes filter_id = 1;
}
message FilterChangesResponse {
bytes info = 1;
}
message FilterLogsRequest {
bytes filter_id = 1;
}
message FilterLogsResponse {
bytes logs = 1;
}
message LogsRequest {
bytes param = 1;
}
message LogsResponse {
bytes logs = 1;
}
\ No newline at end of file
syntax = "proto3";
package ethrpc.v1;
import "google/protobuf/field_mask.proto";
import "google/protobuf/timestamp.proto";
import "ethrpc/v1/resource.proto";
syntax = "proto3";
package ethrpc.v1;
import "base/v1/resource.proto";
import "base/gogo.proto";
message Tx {
base.v1.Address address = 1 [(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
base.v1.Hash hash = 2 [(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
}
\ No newline at end of file
syntax = "proto3";
package ethrpc.v1;
import "google/protobuf/empty.proto";
import "ethrpc/v1/request_response.proto";
import "ethrpc/v1/account_req_res.proto";
import "base/v1/eth_tx.proto";
import "base/v1/resource.proto";
service RpcService {
// web3
rpc Sha3(Sha3Request) returns (Sha3Response) {};
rpc NodeVersion(google.protobuf.Empty) returns (NodeVersionResponse) {};
// network info service
rpc NetVersion(google.protobuf.Empty) returns (NetVersionResponse) {};
rpc NetPeerCount(google.protobuf.Empty) returns (NetPeerCountResponse) {};
// node status
rpc ProtocolVersion(google.protobuf.Empty) returns (ProtocolVersionResponse) {};
rpc Syncing(google.protobuf.Empty) returns (SyncingResponse) {};
rpc Coinbase(google.protobuf.Empty) returns (CoinbaseResponse) {};
rpc Mining(google.protobuf.Empty) returns (MiningResponse) {};
rpc HashRate(google.protobuf.Empty) returns (HashRateResponse) {};
rpc Accounts(google.protobuf.Empty) returns (AccountsResponse) {};
// tx operatoration
rpc GasPrice(google.protobuf.Empty) returns (GasPriceResponse) {};
// block info service
rpc BlockNumber(google.protobuf.Empty) returns (HeightResponse) {};
rpc BlockByHash(BlockByHashRequest) returns (BlockByHashResponse) {};
rpc BlockByNumber(BlockByNumberRequest) returns (BlockByNumberResponse) {};
rpc BlockTransactionCountByHash(BlockTransactionCountByHashRequest) returns (BlockTransactionCountByHashResponse) {};
rpc BlockTransactionCountByNumber(BlockTransactionCountByNumberRequest) returns (BlockTransactionCountByNumberResponse) {};
rpc UncleCountByHash(UncleCountByHashRequest) returns (UncleCountByHashResponse) {};
rpc UncleCountByNumber(UncleCountByNumberRequest) returns (UncleCountByNumberResponse) {};
rpc UncleByBlockHashAndIndex(UncleByBlockHashAndIndexRequest) returns (UncleByBlockHashAndIndexResponse) {};
rpc UncleByBlockNumberAndIndex(UncleByBlockNumberAndIndexRequest) returns (UncleByBlockNumberAndIndexResponse) {};
// compiler
rpc Compilers(CompilersRequest) returns (CompilersResponse) {};
rpc CompileSolidity(CompileSolidityRequest) returns (CompileSolidityResponse) {};
rpc CompileLLL(CompileLLLRequest) returns (CompileLLLResponse) {};
rpc CompileSerpent(CompileSerpentRequest) returns (CompileSerpentResponse) {};
// transaction info service
rpc EstimateGas(EstimateGasRequest) returns (EstimateGasResponse) {};
rpc TransactionByHash(TransactionByHashRequest) returns (TransactionByHashResponse) {};
rpc TransactionByBlockHashAndIndex(TransactionByBlockHashAndIndexRequest) returns (TransactionByBlockHashAndIndexResponse) {};
rpc TransactionByBlockNumberAndIndex(TransactionByBlockNumberAndIndexRequest) returns (TransactionByBlockNumberAndIndexResponse) {};
rpc TransactionReceipt(TransactionReceiptRequest) returns (TransactionReceiptResponse) {};
// account info service
rpc Balance(BalanceRequest) returns (BalanceResponse) {};
rpc Storage(StorageRequest) returns (StorageResponse) {};
rpc Nonce(NonceRequest) returns (NonceResponse) {};
rpc RepeatedNonce(RepeatedNonceRequest) returns (RepeatedNonceResponse) {};
rpc TransactionCount(TransactionCountRequest) returns (TransactionCountResponse) {};
rpc GetCode(GetCodeRequest) returns (GetCodeResponse) {};
rpc Sign(SignRequest) returns (SignResponse) {};
rpc SignTransaction(SignTransactionRequest) returns (SignTransactionResponse) {};
rpc SendTransaction(base.v1.EthTransaction) returns (SendTransactionResponse) {};
rpc SendRawTransaction(base.v1.EthTransaction) returns (SendRawTransactionResponse) {};
rpc Call(CallRequest) returns (CallResponse) {};
// filter
rpc NewFilter(NewFilterRequest) returns (NewFilterResponse) {};
rpc NewBlockFilter(google.protobuf.Empty) returns (NewBlockFilterResponse) {};
rpc PendingTransactionFilter(google.protobuf.Empty) returns (PendingTransactionFilterResponse) {};
rpc UninstallFilter(UninstallFilterRequest) returns (UninstallFilterResponse) {};
rpc FilterChanges(FilterChangesRequest) returns (FilterChangesResponse) {};
rpc FilterLogs(FilterLogsRequest) returns (FilterLogsResponse) {};
rpc Logs(LogsRequest) returns (LogsResponse) {};
// consensus info service
}
\ No newline at end of file
### Tips
1. provide grpc api for client.
2. provide gateway for json-rpc.
module github.com/CaduceusMetaverseProtocol/MetaProtocol
go 1.18
require (
github.com/ethereum/go-ethereum v1.10.26
google.golang.org/grpc v1.51.0
google.golang.org/protobuf v1.28.1
)
require (
github.com/CaduceusMetaverseProtocol/MetaTypes v1.0.0
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/gogo/protobuf v1.3.2
github.com/golang/mock v1.6.0
github.com/golang/protobuf v1.5.2 // indirect
golang.org/x/crypto v0.5.0 // indirect
golang.org/x/net v0.5.0 // indirect
golang.org/x/sys v0.4.0 // indirect
golang.org/x/text v0.6.0 // indirect
google.golang.org/genproto v0.0.0-20221205194025-8222ab48f5fc // indirect
)
replace github.com/CaduceusMetaverseProtocol/MetaTypes => ../MetaTypes-main
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8=
github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o=
github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k=
github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0=
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
github.com/ethereum/go-ethereum v1.10.26 h1:i/7d9RBBwiXCEuyduBQzJw/mKmnvzsN14jqBmytw72s=
github.com/ethereum/go-ethereum v1.10.26/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg=
github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA=
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4=
github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df h1:5Pf6pFKu98ODmgnpvkJ3kFUOQGGLIzLIkbzUHp47618=
google.golang.org/genproto v0.0.0-20221205194025-8222ab48f5fc h1:nUKKji0AarrQKh6XpFEpG3p1TNztxhe7C8TcUvDgXqw=
google.golang.org/genproto v0.0.0-20221205194025-8222ab48f5fc/go.mod h1:1dOng4TWOomJrDGhpXjfCD35wQC6jnC7HpRmOFRqEV0=
google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U=
google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
package main
import (
"context"
"fmt"
"net"
//metabase "github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/base/v1"
metacrypter "github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/crypter/v1"
metanebula "github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/nebula/v1"
metap2p "github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/p2p/v1"
metaring "github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/ring/v1"
metasentry "github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/sentry/v1"
txchecker "github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/txchecker/v1"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/anypb"
)
type P2PServer struct {
metap2p.UnimplementedP2PServiceServer
}
type NebulaServer struct {
metanebula.UnimplementedNebulaServiceServer
}
type SentryServer struct {
metasentry.UnimplementedSentryServiceServer
}
type TxCheckServer struct {
txchecker.UnimplementedTxCheckerServiceServer
}
type RingServer struct {
metaring.UnimplementedRingServiceServer
}
type server struct {
metacrypter.UnimplementedCrypterServiceServer
}
// func (*server) Sign(ctx context.Context, req *metacrypter.SignRequest) (*metacrypter.SignResponse, error) {
// return nil, status.Errorf(codes.Unimplemented, "method Sign not implemented")
// }
//
// func (*server) Verify(ctx context.Context, req *metacrypter.VerifyRequest) (*metacrypter.VerifyResponse, error) {
// return nil, status.Errorf(codes.Unimplemented, "method Verify not implemented")
// }
//
// func (*server) Recover(ctx context.Context, req *metacrypter.RecoverRequest) (*metacrypter.RecoverResponse, error) {
// return nil, status.Errorf(codes.Unimplemented, "method Recover not implemented")
// }
func (*server) BatchSign(ctx context.Context, req *metacrypter.BatchSignRequest) (*metacrypter.BatchSignResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method BatchSign not implemented")
}
func (*server) BatchVerify(ctx context.Context, req *metacrypter.BatchVerifyRequest) (*metacrypter.BatchVerifyResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method BatchVerify not implemented")
}
func (*server) BatchRecover(ctx context.Context, req *metacrypter.BatchRecoverRequest) (*metacrypter.BatchRecoverResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method BatchRecover not implemented")
}
func main() {
lis, err := net.Listen("tcp", ":8972")
if err != nil {
fmt.Printf("failed to listen: %v", err)
return
}
//ethTx := metabase.EthTx{}
//var checkTx metabase.EthTx
//ethTxAsAny, err := pbany(ethTx)
if err != nil {
fmt.Println(err.Error())
return
}
//checkTx.Tx = ethTxAsAny
s := grpc.NewServer() // create grpc server
metacrypter.RegisterCrypterServiceServer(s, &server{}) // register service
err = s.Serve(lis)
if err != nil {
fmt.Printf("failed to serve: %v", err)
return
}
}
func pbany(v interface{}) (*anypb.Any, error) {
pv, ok := v.(proto.Message)
if !ok {
return &anypb.Any{}, fmt.Errorf("%v is not proto.Message", pv)
}
return anypb.New(pv)
}
version: v1
breaking:
use:
- FILE
lint:
use:
- DEFAULT
syntax = "proto3";
package nebula.v1;
import "google/protobuf/field_mask.proto";
import "google/protobuf/timestamp.proto";
import "base/v1/resource.proto";
import "base/v1/meta.proto";
import "base/gogo.proto";
import "nebula/v1/resource.proto";
message NodeVersionRequest { }
message NodeVersionResponse {
string version = 1;
}
message Sha3Request {
// data need to caculate sha3.
bytes data = 1;
}
message Sha3Response {
//
base.v1.Hash hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
}
message NetVersionRequest { }
message NetVersionResponse {
string version = 1;
}
message NetPeerCountRequest { }
message NetPeerCountResponse {
uint32 peer_count = 1;
}
message ProtocolVersionRequest { }
message ProtocolVersionResponse {
string version = 1;
}
message SyncingRequest { }
message SyncingResponse {
base.v1.BigInt start = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
base.v1.BigInt end = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
base.v1.BigInt current = 3[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message CoinbaseRequest { }
message CoinbaseResponse {
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
}
message MiningRequest { }
message MiningResponse {
string status = 1;
}
message HashRateRequest { }
message HashRateResponse {
string result = 1;
}
message GasPriceRequest { }
message GasPriceResponse {
// gas price in wei.
base.v1.BigInt gas_price = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message AccountsRequest { }
message AccountsResponse {
repeated base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
}
message HeightRequest { }
message HeightResponse {
base.v1.BigInt height = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message BalanceRequest {
// request address
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
// request block number
base.v1.BigInt block_id = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message BalanceResponse {
// the address
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
// block height
base.v1.BigInt block_id = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
// balance
base.v1.BigInt balance = 3[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message StorageRequest {
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
base.v1.BigInt block_id = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
base.v1.Hash position = 3[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
}
message StorageResponse {
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
base.v1.BigInt block_id = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
base.v1.Hash position = 3[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
bytes data = 4;
}
message NonceRequest {
// request address
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
// request block number
base.v1.BigInt block_id = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message NonceResponse {
// the address
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
// block height
base.v1.BigInt block_id = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
// nonce
uint64 nonce = 3;
}
message RepeatedNonceRequest {
// request address
repeated base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
// request block number
repeated base.v1.BigInt block_id = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message RepeatedNonceResponse {
// request address
repeated base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
// request block number
repeated base.v1.BigInt block_id = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
// nonce
repeated uint64 nonce = 3;
}
message TransactionCountRequest {
// request address
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
// request block number
base.v1.BigInt block_id = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message TransactionCountResponse {
// the address
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
// block height
base.v1.BigInt block_id = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
// count
uint64 count = 3;
}
message BlockTransactionCountByHashRequest {
base.v1.Hash block_hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
}
message BlockTransactionCountByHashResponse {
base.v1.Hash block_hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
uint32 count = 2;
}
message BlockTransactionCountByNumberRequest {
base.v1.BigInt block_id = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message BlockTransactionCountByNumberResponse {
base.v1.BigInt block_id = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
uint32 count = 2;
}
message UncleCountByHashRequest {
base.v1.Hash block_hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
}
message UncleCountByHashResponse {
base.v1.Hash block_hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
uint32 count = 2;
}
message UncleCountByNumberRequest {
base.v1.BigInt block_id = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message UncleCountByNumberResponse {
base.v1.BigInt block_id = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
uint32 count = 2;
}
message GetCodeRequest {
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
base.v1.BigInt block_id = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message GetCodeResponse {
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
base.v1.BigInt block_id = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
bytes code = 3;
}
message SignRequest {
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
bytes data = 2;
}
message SignResponse {
bytes signature = 1;
}
message SignTransactionRequest {
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
bytes tx_data = 2;
bytes method = 3;
}
message SignTransactionResponse {
bytes signed_tx = 1;
}
message SendTransactionRequest {
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
base.v1.MetaTxBase tx_data = 2;
}
message SendTransactionResponse {
base.v1.Hash tx_hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
}
message SendRawTransactionRequest {
base.v1.MetaProofTx signed_tx = 1;
}
message SendRawTransactionResponse {
base.v1.Hash tx_hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
}
message CallRequest {
base.v1.MetaTxBase signed_tx = 1;
}
message CallResponse {
bytes result = 1;
}
message EstimateGasRequest {
base.v1.MetaTxBase signed_tx = 1;
}
message EstimateGasResponse {
bytes result = 1;
base.v1.BigInt gas = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message BlockByHashRequest {
base.v1.Hash block_hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
}
message BlockByHashResponse {
base.v1.MetaBlock block = 1;
}
message BlockByNumberRequest {
base.v1.BigInt block_id = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message BlockByNumberResponse {
base.v1.MetaBlock block = 1;
}
message TransactionByHashRequest {
base.v1.Hash tx_hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
}
message TransactionByHashResponse {
base.v1.MetaTransaction tx_data = 1;
}
message TransactionByBlockHashAndIndexRequest {
base.v1.Hash block_hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
uint32 index = 2;
}
message TransactionByBlockHashAndIndexResponse {
base.v1.MetaTransaction tx_data = 1;
}
message TransactionByBlockNumberAndIndexRequest {
base.v1.BigInt block_id = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
uint32 index = 2;
}
message TransactionByBlockNumberAndIndexResponse {
base.v1.MetaTransaction tx_data = 1;
}
message TransactionReceiptRequest {
base.v1.Hash tx_hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
}
message TransactionReceiptResponse {
base.v1.MetaReceipt tx_receipt = 1;
}
message UncleByBlockHashAndIndexRequest {
base.v1.Hash block_hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
uint32 index = 2;
}
message UncleByBlockHashAndIndexResponse {
bytes uncle_block = 1;
}
message UncleByBlockNumberAndIndexRequest {
base.v1.BigInt block_id = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
uint32 index = 2;
}
message UncleByBlockNumberAndIndexResponse {
bytes uncle_block = 1;
}
message CompilersRequest {
}
message CompilersResponse {
bytes compilers = 1;
}
message CompileSolidityRequest {
bytes source = 1;
}
message CompileSolidityResponse {
bytes code = 1;
}
message CompileLLLRequest {
bytes source = 1;
}
message CompileLLLResponse {
bytes code = 1;
}
message CompileSerpentRequest {
bytes source = 1;
}
message CompileSerpentResponse {
bytes code = 1;
}
message NewFilterRequest {
bytes param = 1;
}
message NewFilterResponse {
bytes filter_id = 1;
}
message NewBlockFilterRequest { }
message NewBlockFilterResponse {
bytes filter_id = 1;
}
message PendingTransactionFilterRequest { }
message PendingTransactionFilterResponse {
bytes filter_id = 1;
}
message UninstallFilterRequest {
bytes filter_id = 1;
}
message UninstallFilterResponse {
bool result = 1;
}
message FilterChangesRequest {
bytes filter_id = 1;
}
message FilterChangesResponse {
bytes info = 1;
}
message FilterLogsRequest {
bytes filter_id = 1;
}
message FilterLogsResponse {
repeated base.v1.MetaTxLog logs = 1;
}
message LogsRequest {
bytes param = 1;
}
message LogsResponse {
repeated base.v1.MetaTxLog logs = 1;
}
message TestSendTransactionRequest {
base.v1.MetaTransaction tx_data = 1;
}
message TestSendTransactionResponse {
base.v1.Hash tx_hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
}
syntax = "proto3";
package nebula.v1;
import "google/protobuf/field_mask.proto";
import "google/protobuf/timestamp.proto";
import "nebula/v1/resource.proto";
syntax = "proto3";
package nebula.v1;
import "base/v1/resource.proto";
\ No newline at end of file
syntax = "proto3";
package nebula.v1;
import "google/protobuf/empty.proto";
import "nebula/v1/request_response.proto";
import "nebula/v1/account_req_res.proto";
service NebulaService {
// web3
rpc Sha3(Sha3Request) returns (Sha3Response) {};
rpc NodeVersion(google.protobuf.Empty) returns (NodeVersionResponse) {};
// network info service
rpc NetVersion(google.protobuf.Empty) returns (NetVersionResponse) {};
rpc NetPeerCount(google.protobuf.Empty) returns (NetPeerCountResponse) {};
// node status
rpc ProtocolVersion(google.protobuf.Empty) returns (ProtocolVersionResponse) {};
rpc Syncing(google.protobuf.Empty) returns (SyncingResponse) {};
rpc Coinbase(google.protobuf.Empty) returns (CoinbaseResponse) {};
rpc Mining(google.protobuf.Empty) returns (MiningResponse) {};
rpc HashRate(google.protobuf.Empty) returns (HashRateResponse) {};
rpc Accounts(google.protobuf.Empty) returns (AccountsResponse) {};
// tx operatoration
rpc GasPrice(google.protobuf.Empty) returns (GasPriceResponse) {};
// block info service
rpc BlockNumber(google.protobuf.Empty) returns (HeightResponse) {};
rpc BlockByHash(BlockByHashRequest) returns (BlockByHashResponse) {};
rpc BlockByNumber(BlockByNumberRequest) returns (BlockByNumberResponse) {};
rpc BlockTransactionCountByHash(BlockTransactionCountByHashRequest) returns (BlockTransactionCountByHashResponse) {};
rpc BlockTransactionCountByNumber(BlockTransactionCountByNumberRequest) returns (BlockTransactionCountByNumberResponse) {};
rpc UncleCountByHash(UncleCountByHashRequest) returns (UncleCountByHashResponse) {};
rpc UncleCountByNumber(UncleCountByNumberRequest) returns (UncleCountByNumberResponse) {};
rpc UncleByBlockHashAndIndex(UncleByBlockHashAndIndexRequest) returns (UncleByBlockHashAndIndexResponse) {};
rpc UncleByBlockNumberAndIndex(UncleByBlockNumberAndIndexRequest) returns (UncleByBlockNumberAndIndexResponse) {};
// compiler
rpc Compilers(CompilersRequest) returns (CompilersResponse) {};
rpc CompileSolidity(CompileSolidityRequest) returns (CompileSolidityResponse) {};
rpc CompileLLL(CompileLLLRequest) returns (CompileLLLResponse) {};
rpc CompileSerpent(CompileSerpentRequest) returns (CompileSerpentResponse) {};
// transaction info service
rpc EstimateGas(EstimateGasRequest) returns (EstimateGasResponse) {};
rpc TransactionByHash(TransactionByHashRequest) returns (TransactionByHashResponse) {};
rpc TransactionByBlockHashAndIndex(TransactionByBlockHashAndIndexRequest) returns (TransactionByBlockHashAndIndexResponse) {};
rpc TransactionByBlockNumberAndIndex(TransactionByBlockNumberAndIndexRequest) returns (TransactionByBlockNumberAndIndexResponse) {};
rpc TransactionReceipt(TransactionReceiptRequest) returns (TransactionReceiptResponse) {};
// account info service
rpc Balance(BalanceRequest) returns (BalanceResponse) {};
rpc Storage(StorageRequest) returns (StorageResponse) {};
rpc Nonce(NonceRequest) returns (NonceResponse) {};
rpc RepeatedNonce(RepeatedNonceRequest) returns (RepeatedNonceResponse) {};
rpc TransactionCount(TransactionCountRequest) returns (TransactionCountResponse) {};
rpc GetCode(GetCodeRequest) returns (GetCodeResponse) {};
rpc Sign(SignRequest) returns (SignResponse) {};
rpc SignTransaction(SignTransactionRequest) returns (SignTransactionResponse) {};
rpc SendTransaction(SendTransactionRequest) returns (SendTransactionResponse) {};
rpc SendRawTransaction(SendRawTransactionRequest) returns (SendRawTransactionResponse) {};
rpc Call(CallRequest) returns (CallResponse) {};
rpc TestSendTransaction(TestSendTransactionRequest) returns (TestSendTransactionResponse) {};
// filter
rpc NewFilter(NewFilterRequest) returns (NewFilterResponse) {};
rpc NewBlockFilter(google.protobuf.Empty) returns (NewBlockFilterResponse) {};
rpc PendingTransactionFilter(google.protobuf.Empty) returns (PendingTransactionFilterResponse) {};
rpc UninstallFilter(UninstallFilterRequest) returns (UninstallFilterResponse) {};
rpc FilterChanges(FilterChangesRequest) returns (FilterChangesResponse) {};
rpc FilterLogs(FilterLogsRequest) returns (FilterLogsResponse) {};
rpc Logs(LogsRequest) returns (LogsResponse) {};
// consensus info service
}
\ No newline at end of file
syntax = "proto3";
package txchecker.v1;
import "base/v1/meta.proto";
// The standard BatchGet request definition.
message BatchCheckTxRequest {
repeated base.v1.MetaTxBase txs = 1;
}
// The standard BatchGet response definition.
message BatchCheckTxResponse {
// The retrieved shelves.
repeated base.v1.MetaProofTx checked_txs = 1;
}
syntax = "proto3";
package txchecker.v1;
syntax = "proto3";
package txchecker.v1;
import "txchecker/v1/request_response.proto";
service TxCheckerService {
rpc BatchCheckTx(BatchCheckTxRequest) returns (BatchCheckTxResponse) {}
}
# Generated by buf. DO NOT EDIT.
version: v1
version: v1
breaking:
use:
- FILE
lint:
use:
- DEFAULT
syntax = "proto3";
package p2p.v1;
import "google/protobuf/field_mask.proto";
import "google/protobuf/timestamp.proto";
import "p2p/v1/resource.proto";
import "base/v1/batchtx.proto";
import "base/v1/meta.proto";
import "base/v1/resource.proto";
import "base/gogo.proto";
message BroadCastRequest {
MessageHeader header = 1;
bytes data = 2;
}
message BroadCastResponse {
bool status = 1;
}
message BroadCastTxsRequest {
repeated base.v1.BatchTx txs = 1;
}
message BroadCastTxsResponse {
repeated bool status = 1;
}
message BatchTxsHashRequest{
base.v1.Hash hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
}
message BatchTxsHashResponse {
base.v1.Hash hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
repeated base.v1.MetaProofTx txs = 2;
}
message SendDataRequest {
MessageHeader header = 1;
bytes data = 2;
}
message SendDataResponse {
bool success = 1;
}
message SubscribeNewBatchtxRequest {}
message SubscribeNewBatchtxResponse {
repeated base.v1.BatchTx batch_tx = 1;
}
message SubscribeMsgRequest {
P2PMsgType msg_types = 1;
}
message SubscribeMsgResponse {
bytes data = 1;
}
message NetVersionRequest { }
message NetVersionResponse {
bytes version = 1;
}
message NetPeerCountRequest { }
message NetPeerCountResponse {
uint32 peer_count = 1;
}
// PublishRequest is passed when publishing
message PublishRequest {
string topic = 1;
bytes payload = 2;
}
// SubscribeRequest is passed when subscribing
message SubscribeRequest {
string topic = 1;
}
// SubscribeResponse object
message SubscribeResponse {
bytes payload = 1;
}
\ No newline at end of file
syntax = "proto3";
package p2p.v1;
import "google/protobuf/timestamp.proto";
enum P2PMsgType {
P2P_MSG_TYPE_INVALID = 0;
P2P_MSG_TYPE_PING = 1;
P2P_MSG_TYPE_PONG = 2;
}
// shared between all p2p package
message MessageHeader {
// client protocol version
string client_version = 1;
// client type
int32 client_type = 2;
// allows requesters to use request data when processing a response
string id = 3;
// package create time.
google.protobuf.Timestamp create_time = 4;
// id of node that created the message (not the peer that may have sent it). =base58(multihash(nodePubKey))
string node_id = 5;
bool gossip = 6;
// Authoring node Secp256k1 public key (32bytes) - protobufs serielized
bytes node_pubkey = 7;
// signature of full message data.
bytes sign = 8;
}
// HandShake used for check info when peer connect
message HandShakeRequest {
MessageHeader header = 1;
string message = 2;
}
message HandShakeResponse {
MessageHeader header = 1;
string message = 2;
}
// PingRequest used for peer keep alive.
message PingRequest {
MessageHeader header = 1;
string message = 2;
}
message PongResponse {
MessageHeader header = 1;
string message = 2;
}
// Disconnect used for disconnect a peer and give a reason.
message DisconnectRequest {
MessageHeader header = 1;
string reason = 2;
}
message MessageRequest {
MessageHeader header = 1;
int32 message_type = 2;
bytes message_data = 3;
}
message MessageResponse {
MessageHeader header = 1;
int32 message_type = 2;
bytes message_data = 3;
}
syntax = "proto3";
package p2p.v1;
import "p2p/v1/request_response.proto";
import "google/protobuf/empty.proto";
service P2PService {
rpc BroadcastMsg(BroadCastRequest) returns (BroadCastResponse) {}
rpc BroadcastTxsMsg(BroadCastTxsRequest) returns (BroadCastTxsResponse) {}
rpc BatchTxsmsg(BatchTxsHashRequest)returns (BatchTxsHashResponse){}
rpc SendMsg(SendDataRequest) returns (SendDataResponse) {}
// network info service
rpc NetPeerCount(google.protobuf.Empty) returns (NetPeerCountResponse) {};
rpc NetVersion(google.protobuf.Empty) returns (NetVersionResponse) {};
rpc SubscribeNewBatchTx(SubscribeNewBatchtxRequest) returns (stream SubscribeNewBatchtxResponse) {}
rpc SubscribeMsg(SubscribeMsgRequest) returns (stream SubscribeMsgResponse) {}
rpc Publish (PublishRequest) returns (google.protobuf.Empty);
rpc Subscribe (SubscribeRequest) returns (stream SubscribeResponse); // unsubscribe happens on disconnect
}
#!/bin/bash
dir=${1:-""}
#file=${1:-""}
find $dir -name "*.proto" | xargs sed -i '/Hash/s#[0-9 ];# [(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash", (gogoproto.nullable) = false];#'
find $dir -name "*.proto" | xargs sed -i '/Address/s#[0-9 ];# [(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address", (gogoproto.nullable) = false];#'
find $dir -name "*.proto" | xargs sed -i '/BigInt/s#[0-9 ];# [(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt", (gogoproto.nullable) = false];#'
#find $dir -name "*.proto" | xargs sed '/Hash/s#[0-9 ];# [(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash", (gogoproto.nullable) = false];#g'
# Generated by buf. DO NOT EDIT.
version: v1
version: v1
breaking:
use:
- FILE
lint:
use:
- DEFAULT
### Tips
1. receive tx
2. txpool, broadcast batchtx and commit batchtxhash to consensus network over sentry module.
syntax = "proto3";
package ring.v1;
import "google/protobuf/field_mask.proto";
import "nebula/v1/resource.proto";
import "google/protobuf/timestamp.proto";
import "base/v1/resource.proto";
import "base/v1/meta.proto";
import "base/gogo.proto";
message NodeVersionRequest { }
message NodeVersionResponse {
string version = 1;
}
message Sha3Request {
// data need to caculate sha3.
bytes data = 1;
}
message Sha3Response {
//
base.v1.Hash hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
}
message NetVersionRequest { }
message NetVersionResponse {
string version = 1;
}
message NetPeerCountRequest { }
message NetPeerCountResponse {
uint32 peer_count = 1;
}
message ProtocolVersionRequest { }
message ProtocolVersionResponse {
string version = 1;
}
message SyncingRequest { }
message SyncingResponse {
base.v1.BigInt start = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
base.v1.BigInt end = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
base.v1.BigInt current = 3[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message CoinbaseRequest { }
message CoinbaseResponse {
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
}
message MiningRequest { }
message MiningResponse {
string status = 1;
}
message HashRateRequest { }
message HashRateResponse {
string result = 1;
}
message GasPriceRequest { }
message GasPriceResponse {
// gas price in wei.
base.v1.BigInt gas_price = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message AccountsRequest { }
message AccountsResponse {
repeated base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
}
message HeightRequest { }
message HeightResponse {
base.v1.BigInt height = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message BalanceRequest {
// request address
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
// request block number
base.v1.BigInt block_id = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message BalanceResponse {
// the address
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
// block height
base.v1.BigInt block_id = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
// balance
base.v1.BigInt balance = 3[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message StorageRequest {
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
base.v1.BigInt block_id = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
base.v1.Hash position = 3[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
}
message StorageResponse {
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
base.v1.BigInt block_id = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
base.v1.Hash position = 3[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
bytes data = 4;
}
message NonceRequest {
// request address
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
// request block number
base.v1.BigInt block_id = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message NonceResponse {
// the address
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
// block height
base.v1.BigInt block_id = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
// nonce
uint64 nonce = 3;
}
message RepeatedNonceRequest {
// request address
repeated base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
// request block number
repeated base.v1.BigInt block_id = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message RepeatedNonceResponse {
// request address
repeated base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
// request block number
repeated base.v1.BigInt block_id = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
// nonce
repeated uint64 nonce = 3;
}
message TransactionCountRequest {
// request address
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
// request block number
base.v1.BigInt block_id = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message TransactionCountResponse {
// the address
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
// block height
base.v1.BigInt block_id = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
// count
uint64 count = 3;
}
message BlockTransactionCountByHashRequest {
base.v1.Hash block_hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
}
message BlockTransactionCountByHashResponse {
base.v1.Hash block_hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
uint32 count = 2;
}
message BlockTransactionCountByNumberRequest {
base.v1.BigInt block_id = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message BlockTransactionCountByNumberResponse {
base.v1.BigInt block_id = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
uint32 count = 2;
}
message UncleCountByHashRequest {
base.v1.Hash block_hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
}
message UncleCountByHashResponse {
base.v1.Hash block_hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
uint32 count = 2;
}
message UncleCountByNumberRequest {
base.v1.BigInt block_id = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message UncleCountByNumberResponse {
base.v1.BigInt block_id = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
uint32 count = 2;
}
message GetCodeRequest {
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
base.v1.BigInt block_id = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message GetCodeResponse {
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
base.v1.BigInt block_id = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
bytes code = 3;
}
message SignRequest {
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
bytes data = 2;
}
message SignResponse {
bytes signature = 1;
}
message SignTransactionRequest {
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
bytes tx_data = 2;
bytes method = 3;
}
message SignTransactionResponse {
bytes signed_tx = 1;
}
message SendTransactionRequest {
base.v1.Address address = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Address"];
base.v1.MetaTxBase tx_data = 2;
}
message SendTransactionResponse {
base.v1.Hash tx_hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
}
message SendRawTransactionRequest {
base.v1.MetaProofTx signed_tx = 1;
}
message SendRawTransactionResponse {
base.v1.Hash tx_hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
}
message CallRequest {
base.v1.MetaTxBase signed_tx = 1;
}
message CallResponse {
bytes result = 1;
}
message EstimateGasRequest {
base.v1.MetaTxBase signed_tx = 1;
}
message EstimateGasResponse {
bytes result = 1;
base.v1.BigInt gas = 2[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message BlockByHashRequest {
base.v1.Hash block_hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
}
message BlockByHashResponse {
base.v1.MetaBlock block = 1;
}
message BlockByNumberRequest {
base.v1.BigInt block_id = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
}
message BlockByNumberResponse {
base.v1.MetaBlock block = 1;
}
message TransactionByHashRequest {
base.v1.Hash tx_hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
}
message TransactionByHashResponse {
base.v1.MetaTransaction tx_data = 1;
}
message TransactionByBlockHashAndIndexRequest {
base.v1.Hash block_hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
uint32 index = 2;
}
message TransactionByBlockHashAndIndexResponse {
base.v1.MetaTransaction tx_data = 1;
}
message TransactionByBlockNumberAndIndexRequest {
base.v1.BigInt block_id = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
uint32 index = 2;
}
message TransactionByBlockNumberAndIndexResponse {
base.v1.MetaTransaction tx_data = 1;
}
message TransactionReceiptRequest {
base.v1.Hash tx_hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
}
message TransactionReceiptResponse {
base.v1.MetaReceipt tx_receipt = 1;
}
message UncleByBlockHashAndIndexRequest {
base.v1.Hash block_hash = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.Hash"];
uint32 index = 2;
}
message UncleByBlockHashAndIndexResponse {
bytes uncle_block = 1;
}
message UncleByBlockNumberAndIndexRequest {
base.v1.BigInt block_id = 1[(gogoproto.customtype) = "github.com/CaduceusMetaverseProtocol/MetaTypes/types.BigInt"];
uint32 index = 2;
}
message UncleByBlockNumberAndIndexResponse {
bytes uncle_block = 1;
}
message CompilersRequest {
}
message CompilersResponse {
bytes compilers = 1;
}
message CompileSolidityRequest {
bytes source = 1;
}
message CompileSolidityResponse {
bytes code = 1;
}
message CompileLLLRequest {
bytes source = 1;
}
message CompileLLLResponse {
bytes code = 1;
}
message CompileSerpentRequest {
bytes source = 1;
}
message CompileSerpentResponse {
bytes code = 1;
}
message NewFilterRequest {
bytes param = 1;
}
message NewFilterResponse {
bytes filter_id = 1;
}
message NewBlockFilterRequest { }
message NewBlockFilterResponse {
bytes filter_id = 1;
}
message PendingTransactionFilterRequest { }
message PendingTransactionFilterResponse {
bytes filter_id = 1;
}
message UninstallFilterRequest {
bytes filter_id = 1;
}
message UninstallFilterResponse {
bool result = 1;
}
message FilterChangesRequest {
bytes filter_id = 1;
}
message FilterChangesResponse {
bytes info = 1;
}
message FilterLogsRequest {
bytes filter_id = 1;
}
message FilterLogsResponse {
repeated base.v1.MetaTxLog logs = 1;
}
message LogsRequest {
bytes param = 1;
}
message LogsResponse {
repeated base.v1.MetaTxLog logs = 1;
}
\ No newline at end of file
syntax = "proto3";
package ring.v1;
syntax = "proto3";
package ring.v1;
import "google/protobuf/empty.proto";
import "ring/v1/request_response.proto";
import "ring/v1/account_req_res.proto";
import "base/v1/resource.proto";
import "base/v1/eth_tx.proto";
message broadcastEthTxWithFromRequest{
base.v1.EthTransaction ethTx =1;
string from =2;
}
service RingService{
rpc Ping(RequestPing) returns (ResponsePing);
//rpc BroadcastTx(RequestBroadcastTx) returns (ResponseBroadcastTx);
rpc BroadcastTx(broadcastEthTxWithFromRequest) returns (ResponseBroadcastTx);
// web3
rpc Sha3(Sha3Request) returns (Sha3Response) {};
rpc NodeVersion(google.protobuf.Empty) returns (NodeVersionResponse) {};
// network info service
rpc NetVersion(google.protobuf.Empty) returns (NetVersionResponse) {};
rpc NetPeerCount(google.protobuf.Empty) returns (NetPeerCountResponse) {};
// node status
rpc ProtocolVersion(google.protobuf.Empty) returns (ProtocolVersionResponse) {};
rpc Syncing(google.protobuf.Empty) returns (SyncingResponse) {};
rpc Coinbase(google.protobuf.Empty) returns (CoinbaseResponse) {};
rpc Mining(google.protobuf.Empty) returns (MiningResponse) {};
rpc HashRate(google.protobuf.Empty) returns (HashRateResponse) {};
rpc Accounts(google.protobuf.Empty) returns (AccountsResponse) {};
// tx operatoration
rpc GasPrice(google.protobuf.Empty) returns (GasPriceResponse) {};
// block info service
rpc BlockNumber(google.protobuf.Empty) returns (HeightResponse) {};
rpc BlockByHash(BlockByHashRequest) returns (BlockByHashResponse) {};
rpc BlockByNumber(BlockByNumberRequest) returns (BlockByNumberResponse) {};
rpc BlockTransactionCountByHash(BlockTransactionCountByHashRequest) returns (BlockTransactionCountByHashResponse) {};
rpc BlockTransactionCountByNumber(BlockTransactionCountByNumberRequest) returns (BlockTransactionCountByNumberResponse) {};
rpc UncleCountByHash(UncleCountByHashRequest) returns (UncleCountByHashResponse) {};
rpc UncleCountByNumber(UncleCountByNumberRequest) returns (UncleCountByNumberResponse) {};
rpc UncleByBlockHashAndIndex(UncleByBlockHashAndIndexRequest) returns (UncleByBlockHashAndIndexResponse) {};
rpc UncleByBlockNumberAndIndex(UncleByBlockNumberAndIndexRequest) returns (UncleByBlockNumberAndIndexResponse) {};
// compiler
rpc Compilers(CompilersRequest) returns (CompilersResponse) {};
rpc CompileSolidity(CompileSolidityRequest) returns (CompileSolidityResponse) {};
rpc CompileLLL(CompileLLLRequest) returns (CompileLLLResponse) {};
rpc CompileSerpent(CompileSerpentRequest) returns (CompileSerpentResponse) {};
// transaction info service
rpc EstimateGas(EstimateGasRequest) returns (EstimateGasResponse) {};
rpc TransactionByHash(TransactionByHashRequest) returns (TransactionByHashResponse) {};
rpc TransactionByBlockHashAndIndex(TransactionByBlockHashAndIndexRequest) returns (TransactionByBlockHashAndIndexResponse) {};
rpc TransactionByBlockNumberAndIndex(TransactionByBlockNumberAndIndexRequest) returns (TransactionByBlockNumberAndIndexResponse) {};
rpc TransactionReceipt(TransactionReceiptRequest) returns (TransactionReceiptResponse) {};
// account info service
rpc Balance(BalanceRequest) returns (BalanceResponse) {};
rpc Storage(StorageRequest) returns (StorageResponse) {};
rpc Nonce(NonceRequest) returns (NonceResponse) {};
rpc RepeatedNonce(RepeatedNonceRequest) returns (RepeatedNonceResponse) {};
rpc TransactionCount(TransactionCountRequest) returns (TransactionCountResponse) {};
rpc GetCode(GetCodeRequest) returns (GetCodeResponse) {};
rpc Sign(SignRequest) returns (SignResponse) {};
rpc SignTransaction(SignTransactionRequest) returns (SignTransactionResponse) {};
rpc SendTransaction(SendTransactionRequest) returns (SendTransactionResponse) {};
rpc SendRawTransaction(SendRawTransactionRequest) returns (SendRawTransactionResponse) {};
rpc Call(CallRequest) returns (CallResponse) {};
// filter
rpc NewFilter(NewFilterRequest) returns (NewFilterResponse) {};
rpc NewBlockFilter(google.protobuf.Empty) returns (NewBlockFilterResponse) {};
rpc PendingTransactionFilter(google.protobuf.Empty) returns (PendingTransactionFilterResponse) {};
rpc UninstallFilter(UninstallFilterRequest) returns (UninstallFilterResponse) {};
rpc FilterChanges(FilterChangesRequest) returns (FilterChangesResponse) {};
rpc FilterLogs(FilterLogsRequest) returns (FilterLogsResponse) {};
rpc Logs(LogsRequest) returns (LogsResponse) {};
}
message RequestPing {}
message ResponsePing {}
message RequestBroadcastTx {
bytes tx = 1;
}
message ResponseBroadcastTx {
bytes hash =1;
}
\ No newline at end of file
version: v1
breaking:
use:
- FILE
lint:
use:
- DEFAULT
## Tips
1. commit batchtxhash
\ No newline at end of file
syntax = "proto3";
package sentry.v1;
import "google/protobuf/field_mask.proto";
import "google/protobuf/timestamp.proto";
import "sentry/v1/resource.proto";
message LimitInfoRequest {
// block height to get limit info from contract.
//uint32 height = 1;
}
message LimitInfoResponse {
// tx count in one batchTx.
uint32 batch_tx_count = 1;
// batchTx count in one block.
uint32 block_batch_count = 2;
}
message CommitBatchTxRequest {
bytes txdata = 1;
int64 sizem =2; //contain tx count.
}
message CommitBatchTxResponse {
string txhash = 1;
string err_msg = 2;
}
message GetReceiptRequest {
string txhash = 1;
}
message GetReceiptResponse {
bytes receipt_data = 1;
string err_msg = 2;
}
message GetNewBlockRequest {
uint32 last_block = 1;
}
message GetNewBlockResponse {
uint32 block_num = 1;
uint64 block_time = 2;
string batch_txs = 3;
}
message CommitBlockRequest {
string validator = 1;
uint64 block_number = 2;
bytes block_data = 3;
}
message CommitBlockResponse {
string txhash = 1;
string err_msg = 2;
}
message GetConsensusedBlockRequest {
uint64 block_number = 1;
}
message GetConsensusedBlockResponse {
uint64 block_number = 1;
bytes block_data = 2;
}
syntax = "proto3";
package sentry.v1;
syntax = "proto3";
package sentry.v1;
import "sentry/v1/request_response.proto";
import "google/protobuf/empty.proto";
// SentryService methods for other module.
service SentryService {
// for ring
// LimitInfo get latest param for make batch tx.
rpc GetLimitInfo(LimitInfoRequest) returns(LimitInfoResponse) {}
// CommitBatchTx used to commit batch tx to tx-sort-network
rpc CommitBatchTx(CommitBatchTxRequest) returns(CommitBatchTxResponse) {}
// GetTxReceipt from tx-sort-network with txhash
rpc GetBatchTxResult(GetReceiptRequest) returns(GetReceiptResponse) {}
//for validator
// GetNewBlock used for nebula get new virtual block info from contract with lastblock.
rpc GetNewBlock(GetNewBlockRequest) returns(GetNewBlockResponse) {}
// CommitBlock used for nebula commit new block and state info to contract.
rpc CommitBlock(CommitBlockRequest) returns(CommitBlockResponse) {}
// GetConsensusedBlock used for nebula get special block consensus result.
rpc GetConfirmedBlock(GetConsensusedBlockRequest) returns(GetConsensusedBlockResponse) {}
}
## SendTx
```plantuml
@startuml
actor Alice
participant "Ring" as r
participant "Crypter" as c
participant "TxCheck" as t
participant "Sentry" as s
participant "p2p" as p
participant "nebula" as n
n -> p : SubscribeMessage(rethtx, batchtx)
Alice -> r : SendRawTransaction(ethtx)
r -> c : BatchRecoverTx(ethtx)
c -> r : RethTx
r -> t : BatchCheckTx(rethTx)
t -> r : true
r -> Alice : txhash
r -> r : makeBatchTx
r -> s : LimitInfoRequest
s -> r : LimitInfoResponse
r -> s : CommitBatchTx(batchtx)
r -> p : BroadCastMessage(rethtx, batchtx)
p -> n : Stream(rethtx, batchtx)
n -> n : mineblock(rethtx)
Alice -> r : TransactionReceipt(txhash)
r -> n : TransactionReceipt(txhash)
n -> r : receipt
r -> Alice : receipt
@enduml
```
\ No newline at end of file
MIT License
Copyright (c) 2023 CaduceusMetaverseProtocol
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# MetaTypes
This is the definitions of all communal data types.
module github.com/CaduceusMetaverseProtocol/MetaTypes
go 1.18
require golang.org/x/crypto v0.5.0
require golang.org/x/sys v0.4.0 // indirect
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
package tools
import (
"encoding/hex"
"errors"
)
// FromHex returns the bytes represented by the hexadecimal string s.
// s may be prefixed with "0x".
func FromHex(s string) []byte {
if Has0xPrefix(s) {
s = s[2:]
}
if len(s)%2 == 1 {
s = "0" + s
}
return Hex2Bytes(s)
}
// CopyBytes returns an exact copy of the provided bytes.
func CopyBytes(b []byte) (copiedBytes []byte) {
if b == nil {
return nil
}
copiedBytes = make([]byte, len(b))
copy(copiedBytes, b)
return
}
// Has0xPrefix validates str begins with '0x' or '0X'.
func Has0xPrefix(str string) bool {
return len(str) >= 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X')
}
// isHexCharacter returns bool of c being a valid hexadecimal.
func isHexCharacter(c byte) bool {
return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')
}
// IsHex validates whether each byte is valid hexadecimal string.
func IsHex(str string) bool {
if len(str)%2 != 0 {
return false
}
for _, c := range []byte(str) {
if !isHexCharacter(c) {
return false
}
}
return true
}
// Bytes2Hex returns the hexadecimal encoding of d.
func Bytes2Hex(d []byte) string {
return hex.EncodeToString(d)
}
// Hex2Bytes returns the bytes represented by the hexadecimal string str.
func Hex2Bytes(str string) []byte {
h, _ := hex.DecodeString(str)
return h
}
// Hex2BytesFixed returns bytes of a specified fixed length flen.
func Hex2BytesFixed(str string, flen int) []byte {
h, _ := hex.DecodeString(str)
if len(h) == flen {
return h
}
if len(h) > flen {
return h[len(h)-flen:]
}
hh := make([]byte, flen)
copy(hh[flen-len(h):flen], h)
return hh
}
// ParseHexOrString tries to hexdecode b, but if the prefix is missing, it instead just returns the raw bytes
func ParseHexOrString(str string) ([]byte, error) {
b, err := Decode(str)
if errors.Is(err, ErrMissingPrefix) {
return []byte(str), nil
}
return b, err
}
// RightPadBytes zero-pads slice to the right up to length l.
func RightPadBytes(slice []byte, l int) []byte {
if l <= len(slice) {
return slice
}
padded := make([]byte, l)
copy(padded, slice)
return padded
}
// LeftPadBytes zero-pads slice to the left up to length l.
func LeftPadBytes(slice []byte, l int) []byte {
if l <= len(slice) {
return slice
}
padded := make([]byte, l)
copy(padded[l-len(slice):], slice)
return padded
}
// TrimLeftZeroes returns a subslice of s without leading zeroes
func TrimLeftZeroes(s []byte) []byte {
idx := 0
for ; idx < len(s); idx++ {
if s[idx] != 0 {
break
}
}
return s[idx:]
}
// TrimRightZeroes returns a subslice of s without trailing zeroes
func TrimRightZeroes(s []byte) []byte {
idx := len(s)
for ; idx > 0; idx-- {
if s[idx-1] != 0 {
break
}
}
return s[:idx]
}
package tools
import (
"encoding/hex"
"fmt"
"math/big"
"strconv"
)
const uintBits = 32 << (uint64(^uint(0)) >> 63)
// Errors
var (
ErrEmptyString = &decError{"empty hex string"}
ErrSyntax = &decError{"invalid hex string"}
ErrMissingPrefix = &decError{"hex string without 0x prefix"}
ErrOddLength = &decError{"hex string of odd length"}
ErrEmptyNumber = &decError{"hex string \"0x\""}
ErrLeadingZero = &decError{"hex number with leading zero digits"}
ErrUint64Range = &decError{"hex number > 64 bits"}
ErrUintRange = &decError{fmt.Sprintf("hex number > %d bits", uintBits)}
ErrBig256Range = &decError{"hex number > 256 bits"}
)
type decError struct{ msg string }
func (err decError) Error() string { return err.msg }
// Decode decodes a hex string with 0x prefix.
func Decode(input string) ([]byte, error) {
if len(input) == 0 {
return nil, ErrEmptyString
}
if !Has0xPrefix(input) {
return nil, ErrMissingPrefix
}
b, err := hex.DecodeString(input[2:])
if err != nil {
err = mapError(err)
}
return b, err
}
// MustDecode decodes a hex string with 0x prefix. It panics for invalid input.
func MustDecode(input string) []byte {
dec, err := Decode(input)
if err != nil {
panic(err)
}
return dec
}
// Encode encodes b as a hex string with 0x prefix.
func Encode(b []byte) string {
enc := make([]byte, len(b)*2+2)
copy(enc, "0x")
hex.Encode(enc[2:], b)
return string(enc)
}
// DecodeUint64 decodes a hex string with 0x prefix as a quantity.
func DecodeUint64(input string) (uint64, error) {
raw, err := checkNumber(input)
if err != nil {
return 0, err
}
dec, err := strconv.ParseUint(raw, 16, 64)
if err != nil {
err = mapError(err)
}
return dec, err
}
// MustDecodeUint64 decodes a hex string with 0x prefix as a quantity.
// It panics for invalid input.
func MustDecodeUint64(input string) uint64 {
dec, err := DecodeUint64(input)
if err != nil {
panic(err)
}
return dec
}
// EncodeUint64 encodes i as a hex string with 0x prefix.
func EncodeUint64(i uint64) string {
enc := make([]byte, 2, 10)
copy(enc, "0x")
return string(strconv.AppendUint(enc, i, 16))
}
var bigWordNibbles int
func init() {
// This is a weird way to compute the number of nibbles required for big.Word.
// The usual way would be to use constant arithmetic but go vet can't handle that.
b, _ := new(big.Int).SetString("FFFFFFFFFF", 16)
switch len(b.Bits()) {
case 1:
bigWordNibbles = 16
case 2:
bigWordNibbles = 8
default:
panic("weird big.Word size")
}
}
// DecodeBig decodes a hex string with 0x prefix as a quantity.
// Numbers larger than 256 bits are not accepted.
func DecodeBig(input string) (*big.Int, error) {
raw, err := checkNumber(input)
if err != nil {
return nil, err
}
if len(raw) > 64 {
return nil, ErrBig256Range
}
words := make([]big.Word, len(raw)/bigWordNibbles+1)
end := len(raw)
for i := range words {
start := end - bigWordNibbles
if start < 0 {
start = 0
}
for ri := start; ri < end; ri++ {
nib := decodeNibble(raw[ri])
if nib == badNibble {
return nil, ErrSyntax
}
words[i] *= 16
words[i] += big.Word(nib)
}
end = start
}
dec := new(big.Int).SetBits(words)
return dec, nil
}
// MustDecodeBig decodes a hex string with 0x prefix as a quantity.
// It panics for invalid input.
func MustDecodeBig(input string) *big.Int {
dec, err := DecodeBig(input)
if err != nil {
panic(err)
}
return dec
}
// EncodeBig encodes bigint as a hex string with 0x prefix.
func EncodeBig(bigint *big.Int) string {
if sign := bigint.Sign(); sign == 0 {
return "0x0"
} else if sign > 0 {
return "0x" + bigint.Text(16)
} else {
return "-0x" + bigint.Text(16)[1:]
}
}
func checkNumber(input string) (raw string, err error) {
if len(input) == 0 {
return "", ErrEmptyString
}
if !Has0xPrefix(input) {
return "", ErrMissingPrefix
}
input = input[2:]
if len(input) == 0 {
return "", ErrEmptyNumber
}
if len(input) > 1 && input[0] == '0' {
return "", ErrLeadingZero
}
return input, nil
}
const badNibble = ^uint64(0)
func decodeNibble(in byte) uint64 {
switch {
case in >= '0' && in <= '9':
return uint64(in - '0')
case in >= 'A' && in <= 'F':
return uint64(in - 'A' + 10)
case in >= 'a' && in <= 'f':
return uint64(in - 'a' + 10)
default:
return badNibble
}
}
func mapError(err error) error {
if err, ok := err.(*strconv.NumError); ok {
switch err.Err {
case strconv.ErrRange:
return ErrUint64Range
case strconv.ErrSyntax:
return ErrSyntax
}
}
if _, ok := err.(hex.InvalidByteError); ok {
return ErrSyntax
}
if err == hex.ErrLength {
return ErrOddLength
}
return err
}
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package tools
import (
"bytes"
"math/big"
"testing"
)
type marshalTest struct {
input interface{}
want string
}
type unmarshalTest struct {
input string
want interface{}
wantErr error // if set, decoding must fail on any platform
wantErr32bit error // if set, decoding must fail on 32bit platforms (used for Uint tests)
}
var (
encodeBytesTests = []marshalTest{
{[]byte{}, "0x"},
{[]byte{0}, "0x00"},
{[]byte{0, 0, 1, 2}, "0x00000102"},
}
encodeBigTests = []marshalTest{
{referenceBig("0"), "0x0"},
{referenceBig("1"), "0x1"},
{referenceBig("ff"), "0xff"},
{referenceBig("112233445566778899aabbccddeeff"), "0x112233445566778899aabbccddeeff"},
{referenceBig("80a7f2c1bcc396c00"), "0x80a7f2c1bcc396c00"},
{referenceBig("-80a7f2c1bcc396c00"), "-0x80a7f2c1bcc396c00"},
}
encodeUint64Tests = []marshalTest{
{uint64(0), "0x0"},
{uint64(1), "0x1"},
{uint64(0xff), "0xff"},
{uint64(0x1122334455667788), "0x1122334455667788"},
}
encodeUintTests = []marshalTest{
{uint(0), "0x0"},
{uint(1), "0x1"},
{uint(0xff), "0xff"},
{uint(0x11223344), "0x11223344"},
}
decodeBytesTests = []unmarshalTest{
// invalid
{input: ``, wantErr: ErrEmptyString},
{input: `0`, wantErr: ErrMissingPrefix},
{input: `0x0`, wantErr: ErrOddLength},
{input: `0x023`, wantErr: ErrOddLength},
{input: `0xxx`, wantErr: ErrSyntax},
{input: `0x01zz01`, wantErr: ErrSyntax},
// valid
{input: `0x`, want: []byte{}},
{input: `0X`, want: []byte{}},
{input: `0x02`, want: []byte{0x02}},
{input: `0X02`, want: []byte{0x02}},
{input: `0xffffffffff`, want: []byte{0xff, 0xff, 0xff, 0xff, 0xff}},
{
input: `0xffffffffffffffffffffffffffffffffffff`,
want: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
},
}
decodeBigTests = []unmarshalTest{
// invalid
{input: `0`, wantErr: ErrMissingPrefix},
{input: `0x`, wantErr: ErrEmptyNumber},
{input: `0x01`, wantErr: ErrLeadingZero},
{input: `0xx`, wantErr: ErrSyntax},
{input: `0x1zz01`, wantErr: ErrSyntax},
{
input: `0x10000000000000000000000000000000000000000000000000000000000000000`,
wantErr: ErrBig256Range,
},
// valid
{input: `0x0`, want: big.NewInt(0)},
{input: `0x2`, want: big.NewInt(0x2)},
{input: `0x2F2`, want: big.NewInt(0x2f2)},
{input: `0X2F2`, want: big.NewInt(0x2f2)},
{input: `0x1122aaff`, want: big.NewInt(0x1122aaff)},
{input: `0xbBb`, want: big.NewInt(0xbbb)},
{input: `0xfffffffff`, want: big.NewInt(0xfffffffff)},
{
input: `0x112233445566778899aabbccddeeff`,
want: referenceBig("112233445566778899aabbccddeeff"),
},
{
input: `0xffffffffffffffffffffffffffffffffffff`,
want: referenceBig("ffffffffffffffffffffffffffffffffffff"),
},
{
input: `0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff`,
want: referenceBig("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
},
}
decodeUint64Tests = []unmarshalTest{
// invalid
{input: `0`, wantErr: ErrMissingPrefix},
{input: `0x`, wantErr: ErrEmptyNumber},
{input: `0x01`, wantErr: ErrLeadingZero},
{input: `0xfffffffffffffffff`, wantErr: ErrUint64Range},
{input: `0xx`, wantErr: ErrSyntax},
{input: `0x1zz01`, wantErr: ErrSyntax},
// valid
{input: `0x0`, want: uint64(0)},
{input: `0x2`, want: uint64(0x2)},
{input: `0x2F2`, want: uint64(0x2f2)},
{input: `0X2F2`, want: uint64(0x2f2)},
{input: `0x1122aaff`, want: uint64(0x1122aaff)},
{input: `0xbbb`, want: uint64(0xbbb)},
{input: `0xffffffffffffffff`, want: uint64(0xffffffffffffffff)},
}
)
func TestEncode(t *testing.T) {
for _, test := range encodeBytesTests {
enc := Encode(test.input.([]byte))
if enc != test.want {
t.Errorf("input %x: wrong encoding %s", test.input, enc)
}
}
}
func TestDecode(t *testing.T) {
for _, test := range decodeBytesTests {
dec, err := Decode(test.input)
if !checkError(t, test.input, err, test.wantErr) {
continue
}
if !bytes.Equal(test.want.([]byte), dec) {
t.Errorf("input %s: value mismatch: got %x, want %x", test.input, dec, test.want)
continue
}
}
}
func TestEncodeBig(t *testing.T) {
for _, test := range encodeBigTests {
enc := EncodeBig(test.input.(*big.Int))
if enc != test.want {
t.Errorf("input %x: wrong encoding %s", test.input, enc)
}
}
}
func TestDecodeBig(t *testing.T) {
for _, test := range decodeBigTests {
dec, err := DecodeBig(test.input)
if !checkError(t, test.input, err, test.wantErr) {
continue
}
if dec.Cmp(test.want.(*big.Int)) != 0 {
t.Errorf("input %s: value mismatch: got %x, want %x", test.input, dec, test.want)
continue
}
}
}
func TestEncodeUint64(t *testing.T) {
for _, test := range encodeUint64Tests {
enc := EncodeUint64(test.input.(uint64))
if enc != test.want {
t.Errorf("input %x: wrong encoding %s", test.input, enc)
}
}
}
func TestDecodeUint64(t *testing.T) {
for _, test := range decodeUint64Tests {
dec, err := DecodeUint64(test.input)
if !checkError(t, test.input, err, test.wantErr) {
continue
}
if dec != test.want.(uint64) {
t.Errorf("input %s: value mismatch: got %x, want %x", test.input, dec, test.want)
continue
}
}
}
func BenchmarkEncodeBig(b *testing.B) {
for _, bench := range encodeBigTests {
b.Run(bench.want, func(b *testing.B) {
b.ReportAllocs()
bigint := bench.input.(*big.Int)
for i := 0; i < b.N; i++ {
EncodeBig(bigint)
}
})
}
}
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package tools
import (
"encoding/hex"
"encoding/json"
"fmt"
"math/big"
"reflect"
"strconv"
)
var (
bytesT = reflect.TypeOf(Bytes(nil))
bigT = reflect.TypeOf((*Big)(nil))
uintT = reflect.TypeOf(Uint(0))
uint64T = reflect.TypeOf(Uint64(0))
)
// Bytes marshals/unmarshals as a JSON string with 0x prefix.
// The empty slice marshals as "0x".
type Bytes []byte
// MarshalText implements encoding.TextMarshaler
func (b Bytes) MarshalText() ([]byte, error) {
result := make([]byte, len(b)*2+2)
copy(result, `0x`)
hex.Encode(result[2:], b)
return result, nil
}
// UnmarshalJSON implements json.Unmarshaler.
func (b *Bytes) UnmarshalJSON(input []byte) error {
if !isString(input) {
return errNonString(bytesT)
}
return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bytesT)
}
// UnmarshalText implements encoding.TextUnmarshaler.
func (b *Bytes) UnmarshalText(input []byte) error {
raw, err := checkText(input, true)
if err != nil {
return err
}
dec := make([]byte, len(raw)/2)
if _, err = hex.Decode(dec, raw); err != nil {
err = mapError(err)
} else {
*b = dec
}
return err
}
// String returns the hex encoding of b.
func (b Bytes) String() string {
return Encode(b)
}
// ImplementsGraphQLType returns true if Bytes implements the specified GraphQL type.
func (b Bytes) ImplementsGraphQLType(name string) bool { return name == "Bytes" }
// UnmarshalGraphQL unmarshals the provided GraphQL query data.
func (b *Bytes) UnmarshalGraphQL(input interface{}) error {
var err error
switch input := input.(type) {
case string:
data, err := Decode(input)
if err != nil {
return err
}
*b = data
default:
err = fmt.Errorf("unexpected type %T for Bytes", input)
}
return err
}
// UnmarshalFixedJSON decodes the input as a string with 0x prefix. The length of out
// determines the required input length. This function is commonly used to implement the
// UnmarshalJSON method for fixed-size types.
func UnmarshalFixedJSON(typ reflect.Type, input, out []byte) error {
if !isString(input) {
return errNonString(typ)
}
return wrapTypeError(UnmarshalFixedText(typ.String(), input[1:len(input)-1], out), typ)
}
// UnmarshalFixedText decodes the input as a string with 0x prefix. The length of out
// determines the required input length. This function is commonly used to implement the
// UnmarshalText method for fixed-size types.
func UnmarshalFixedText(typname string, input, out []byte) error {
raw, err := checkText(input, true)
if err != nil {
return err
}
if len(raw)/2 != len(out) {
return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname)
}
// Pre-verify syntax before modifying out.
for _, b := range raw {
if decodeNibble(b) == badNibble {
return ErrSyntax
}
}
hex.Decode(out, raw)
return nil
}
// UnmarshalFixedUnprefixedText decodes the input as a string with optional 0x prefix. The
// length of out determines the required input length. This function is commonly used to
// implement the UnmarshalText method for fixed-size types.
func UnmarshalFixedUnprefixedText(typname string, input, out []byte) error {
raw, err := checkText(input, false)
if err != nil {
return err
}
if len(raw)/2 != len(out) {
return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname)
}
// Pre-verify syntax before modifying out.
for _, b := range raw {
if decodeNibble(b) == badNibble {
return ErrSyntax
}
}
hex.Decode(out, raw)
return nil
}
// Big marshals/unmarshals as a JSON string with 0x prefix.
// The zero value marshals as "0x0".
//
// Negative integers are not supported at this time. Attempting to marshal them will
// return an error. Values larger than 256bits are rejected by Unmarshal but will be
// marshaled without error.
type Big big.Int
// MarshalText implements encoding.TextMarshaler
func (b Big) MarshalText() ([]byte, error) {
return []byte(EncodeBig((*big.Int)(&b))), nil
}
// UnmarshalJSON implements json.Unmarshaler.
func (b *Big) UnmarshalJSON(input []byte) error {
if !isString(input) {
return errNonString(bigT)
}
return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bigT)
}
// UnmarshalText implements encoding.TextUnmarshaler
func (b *Big) UnmarshalText(input []byte) error {
raw, err := checkNumberText(input)
if err != nil {
return err
}
if len(raw) > 64 {
return ErrBig256Range
}
words := make([]big.Word, len(raw)/bigWordNibbles+1)
end := len(raw)
for i := range words {
start := end - bigWordNibbles
if start < 0 {
start = 0
}
for ri := start; ri < end; ri++ {
nib := decodeNibble(raw[ri])
if nib == badNibble {
return ErrSyntax
}
words[i] *= 16
words[i] += big.Word(nib)
}
end = start
}
var dec big.Int
dec.SetBits(words)
*b = (Big)(dec)
return nil
}
// ToInt converts b to a big.Int.
func (b *Big) ToInt() *big.Int {
return (*big.Int)(b)
}
// String returns the hex encoding of b.
func (b *Big) String() string {
return EncodeBig(b.ToInt())
}
// ImplementsGraphQLType returns true if Big implements the provided GraphQL type.
func (b Big) ImplementsGraphQLType(name string) bool { return name == "BigInt" }
// UnmarshalGraphQL unmarshals the provided GraphQL query data.
func (b *Big) UnmarshalGraphQL(input interface{}) error {
var err error
switch input := input.(type) {
case string:
return b.UnmarshalText([]byte(input))
case int32:
var num big.Int
num.SetInt64(int64(input))
*b = Big(num)
default:
err = fmt.Errorf("unexpected type %T for BigInt", input)
}
return err
}
// Uint64 marshals/unmarshals as a JSON string with 0x prefix.
// The zero value marshals as "0x0".
type Uint64 uint64
// MarshalText implements encoding.TextMarshaler.
func (b Uint64) MarshalText() ([]byte, error) {
buf := make([]byte, 2, 10)
copy(buf, `0x`)
buf = strconv.AppendUint(buf, uint64(b), 16)
return buf, nil
}
// UnmarshalJSON implements json.Unmarshaler.
func (b *Uint64) UnmarshalJSON(input []byte) error {
if !isString(input) {
return errNonString(uint64T)
}
return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), uint64T)
}
// UnmarshalText implements encoding.TextUnmarshaler
func (b *Uint64) UnmarshalText(input []byte) error {
raw, err := checkNumberText(input)
if err != nil {
return err
}
if len(raw) > 16 {
return ErrUint64Range
}
var dec uint64
for _, byte := range raw {
nib := decodeNibble(byte)
if nib == badNibble {
return ErrSyntax
}
dec *= 16
dec += nib
}
*b = Uint64(dec)
return nil
}
// String returns the hex encoding of b.
func (b Uint64) String() string {
return EncodeUint64(uint64(b))
}
// ImplementsGraphQLType returns true if Uint64 implements the provided GraphQL type.
func (b Uint64) ImplementsGraphQLType(name string) bool { return name == "Long" }
// UnmarshalGraphQL unmarshals the provided GraphQL query data.
func (b *Uint64) UnmarshalGraphQL(input interface{}) error {
var err error
switch input := input.(type) {
case string:
return b.UnmarshalText([]byte(input))
case int32:
*b = Uint64(input)
default:
err = fmt.Errorf("unexpected type %T for Long", input)
}
return err
}
// Uint marshals/unmarshals as a JSON string with 0x prefix.
// The zero value marshals as "0x0".
type Uint uint
// MarshalText implements encoding.TextMarshaler.
func (b Uint) MarshalText() ([]byte, error) {
return Uint64(b).MarshalText()
}
// UnmarshalJSON implements json.Unmarshaler.
func (b *Uint) UnmarshalJSON(input []byte) error {
if !isString(input) {
return errNonString(uintT)
}
return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), uintT)
}
// UnmarshalText implements encoding.TextUnmarshaler.
func (b *Uint) UnmarshalText(input []byte) error {
var u64 Uint64
err := u64.UnmarshalText(input)
if u64 > Uint64(^uint(0)) || err == ErrUint64Range {
return ErrUintRange
} else if err != nil {
return err
}
*b = Uint(u64)
return nil
}
// String returns the hex encoding of b.
func (b Uint) String() string {
return EncodeUint64(uint64(b))
}
func isString(input []byte) bool {
return len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"'
}
func bytesHave0xPrefix(input []byte) bool {
return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X')
}
func checkText(input []byte, wantPrefix bool) ([]byte, error) {
if len(input) == 0 {
return nil, nil // empty strings are allowed
}
if bytesHave0xPrefix(input) {
input = input[2:]
} else if wantPrefix {
return nil, ErrMissingPrefix
}
if len(input)%2 != 0 {
return nil, ErrOddLength
}
return input, nil
}
func checkNumberText(input []byte) (raw []byte, err error) {
if len(input) == 0 {
return nil, nil // empty strings are allowed
}
if !bytesHave0xPrefix(input) {
return nil, ErrMissingPrefix
}
input = input[2:]
if len(input) == 0 {
return nil, ErrEmptyNumber
}
if len(input) > 1 && input[0] == '0' {
return nil, ErrLeadingZero
}
return input, nil
}
func wrapTypeError(err error, typ reflect.Type) error {
if _, ok := err.(*decError); ok {
return &json.UnmarshalTypeError{Value: err.Error(), Type: typ}
}
return err
}
func errNonString(typ reflect.Type) error {
return &json.UnmarshalTypeError{Value: "non-string", Type: typ}
}
// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package tools_test
import (
"encoding/json"
"fmt"
"github.com/CaduceusMetaverseProtocol/MetaTypes/tools"
)
type MyType [5]byte
func (v *MyType) UnmarshalText(input []byte) error {
return tools.UnmarshalFixedText("MyType", input, v[:])
}
func (v MyType) String() string {
return tools.Bytes(v[:]).String()
}
func ExampleUnmarshalFixedText() {
var v1, v2 MyType
fmt.Println("v1 error:", json.Unmarshal([]byte(`"0x01"`), &v1))
fmt.Println("v2 error:", json.Unmarshal([]byte(`"0x0101010101"`), &v2))
fmt.Println("v2:", v2)
// Output:
// v1 error: hex string has length 2, want 10 for MyType
// v2 error: <nil>
// v2: 0x0101010101
}
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package tools
import (
"bytes"
"encoding/hex"
"encoding/json"
"errors"
"math/big"
"testing"
)
func checkError(t *testing.T, input string, got, want error) bool {
if got == nil {
if want != nil {
t.Errorf("input %s: got no error, want %q", input, want)
return false
}
return true
}
if want == nil {
t.Errorf("input %s: unexpected error %q", input, got)
} else if got.Error() != want.Error() {
t.Errorf("input %s: got error %q, want %q", input, got, want)
}
return false
}
func referenceBig(s string) *big.Int {
b, ok := new(big.Int).SetString(s, 16)
if !ok {
panic("invalid")
}
return b
}
func referenceBytes(s string) []byte {
b, err := hex.DecodeString(s)
if err != nil {
panic(err)
}
return b
}
var errJSONEOF = errors.New("unexpected end of JSON input")
var unmarshalBytesTests = []unmarshalTest{
// invalid encoding
{input: "", wantErr: errJSONEOF},
{input: "null", wantErr: errNonString(bytesT)},
{input: "10", wantErr: errNonString(bytesT)},
{input: `"0"`, wantErr: wrapTypeError(ErrMissingPrefix, bytesT)},
{input: `"0x0"`, wantErr: wrapTypeError(ErrOddLength, bytesT)},
{input: `"0xxx"`, wantErr: wrapTypeError(ErrSyntax, bytesT)},
{input: `"0x01zz01"`, wantErr: wrapTypeError(ErrSyntax, bytesT)},
// valid encoding
{input: `""`, want: referenceBytes("")},
{input: `"0x"`, want: referenceBytes("")},
{input: `"0x02"`, want: referenceBytes("02")},
{input: `"0X02"`, want: referenceBytes("02")},
{input: `"0xffffffffff"`, want: referenceBytes("ffffffffff")},
{
input: `"0xffffffffffffffffffffffffffffffffffff"`,
want: referenceBytes("ffffffffffffffffffffffffffffffffffff"),
},
}
func TestUnmarshalBytes(t *testing.T) {
for _, test := range unmarshalBytesTests {
var v Bytes
err := json.Unmarshal([]byte(test.input), &v)
if !checkError(t, test.input, err, test.wantErr) {
continue
}
if !bytes.Equal(test.want.([]byte), v) {
t.Errorf("input %s: value mismatch: got %x, want %x", test.input, &v, test.want)
continue
}
}
}
func BenchmarkUnmarshalBytes(b *testing.B) {
input := []byte(`"0x123456789abcdef123456789abcdef"`)
for i := 0; i < b.N; i++ {
var v Bytes
if err := v.UnmarshalJSON(input); err != nil {
b.Fatal(err)
}
}
}
func TestMarshalBytes(t *testing.T) {
for _, test := range encodeBytesTests {
in := test.input.([]byte)
out, err := json.Marshal(Bytes(in))
if err != nil {
t.Errorf("%x: %v", in, err)
continue
}
if want := `"` + test.want + `"`; string(out) != want {
t.Errorf("%x: MarshalJSON output mismatch: got %q, want %q", in, out, want)
continue
}
if out := Bytes(in).String(); out != test.want {
t.Errorf("%x: String mismatch: got %q, want %q", in, out, test.want)
continue
}
}
}
var unmarshalBigTests = []unmarshalTest{
// invalid encoding
{input: "", wantErr: errJSONEOF},
{input: "null", wantErr: errNonString(bigT)},
{input: "10", wantErr: errNonString(bigT)},
{input: `"0"`, wantErr: wrapTypeError(ErrMissingPrefix, bigT)},
{input: `"0x"`, wantErr: wrapTypeError(ErrEmptyNumber, bigT)},
{input: `"0x01"`, wantErr: wrapTypeError(ErrLeadingZero, bigT)},
{input: `"0xx"`, wantErr: wrapTypeError(ErrSyntax, bigT)},
{input: `"0x1zz01"`, wantErr: wrapTypeError(ErrSyntax, bigT)},
{
input: `"0x10000000000000000000000000000000000000000000000000000000000000000"`,
wantErr: wrapTypeError(ErrBig256Range, bigT),
},
// valid encoding
{input: `""`, want: big.NewInt(0)},
{input: `"0x0"`, want: big.NewInt(0)},
{input: `"0x2"`, want: big.NewInt(0x2)},
{input: `"0x2F2"`, want: big.NewInt(0x2f2)},
{input: `"0X2F2"`, want: big.NewInt(0x2f2)},
{input: `"0x1122aaff"`, want: big.NewInt(0x1122aaff)},
{input: `"0xbBb"`, want: big.NewInt(0xbbb)},
{input: `"0xfffffffff"`, want: big.NewInt(0xfffffffff)},
{
input: `"0x112233445566778899aabbccddeeff"`,
want: referenceBig("112233445566778899aabbccddeeff"),
},
{
input: `"0xffffffffffffffffffffffffffffffffffff"`,
want: referenceBig("ffffffffffffffffffffffffffffffffffff"),
},
{
input: `"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"`,
want: referenceBig("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
},
}
func TestUnmarshalBig(t *testing.T) {
for _, test := range unmarshalBigTests {
var v Big
err := json.Unmarshal([]byte(test.input), &v)
if !checkError(t, test.input, err, test.wantErr) {
continue
}
if test.want != nil && test.want.(*big.Int).Cmp((*big.Int)(&v)) != 0 {
t.Errorf("input %s: value mismatch: got %x, want %x", test.input, (*big.Int)(&v), test.want)
continue
}
}
}
func BenchmarkUnmarshalBig(b *testing.B) {
input := []byte(`"0x123456789abcdef123456789abcdef"`)
for i := 0; i < b.N; i++ {
var v Big
if err := v.UnmarshalJSON(input); err != nil {
b.Fatal(err)
}
}
}
func TestMarshalBig(t *testing.T) {
for _, test := range encodeBigTests {
in := test.input.(*big.Int)
out, err := json.Marshal((*Big)(in))
if err != nil {
t.Errorf("%d: %v", in, err)
continue
}
if want := `"` + test.want + `"`; string(out) != want {
t.Errorf("%d: MarshalJSON output mismatch: got %q, want %q", in, out, want)
continue
}
if out := (*Big)(in).String(); out != test.want {
t.Errorf("%x: String mismatch: got %q, want %q", in, out, test.want)
continue
}
}
}
var unmarshalUint64Tests = []unmarshalTest{
// invalid encoding
{input: "", wantErr: errJSONEOF},
{input: "null", wantErr: errNonString(uint64T)},
{input: "10", wantErr: errNonString(uint64T)},
{input: `"0"`, wantErr: wrapTypeError(ErrMissingPrefix, uint64T)},
{input: `"0x"`, wantErr: wrapTypeError(ErrEmptyNumber, uint64T)},
{input: `"0x01"`, wantErr: wrapTypeError(ErrLeadingZero, uint64T)},
{input: `"0xfffffffffffffffff"`, wantErr: wrapTypeError(ErrUint64Range, uint64T)},
{input: `"0xx"`, wantErr: wrapTypeError(ErrSyntax, uint64T)},
{input: `"0x1zz01"`, wantErr: wrapTypeError(ErrSyntax, uint64T)},
// valid encoding
{input: `""`, want: uint64(0)},
{input: `"0x0"`, want: uint64(0)},
{input: `"0x2"`, want: uint64(0x2)},
{input: `"0x2F2"`, want: uint64(0x2f2)},
{input: `"0X2F2"`, want: uint64(0x2f2)},
{input: `"0x1122aaff"`, want: uint64(0x1122aaff)},
{input: `"0xbbb"`, want: uint64(0xbbb)},
{input: `"0xffffffffffffffff"`, want: uint64(0xffffffffffffffff)},
}
func TestUnmarshalUint64(t *testing.T) {
for _, test := range unmarshalUint64Tests {
var v Uint64
err := json.Unmarshal([]byte(test.input), &v)
if !checkError(t, test.input, err, test.wantErr) {
continue
}
if uint64(v) != test.want.(uint64) {
t.Errorf("input %s: value mismatch: got %d, want %d", test.input, v, test.want)
continue
}
}
}
func BenchmarkUnmarshalUint64(b *testing.B) {
input := []byte(`"0x123456789abcdf"`)
for i := 0; i < b.N; i++ {
var v Uint64
v.UnmarshalJSON(input)
}
}
func TestMarshalUint64(t *testing.T) {
for _, test := range encodeUint64Tests {
in := test.input.(uint64)
out, err := json.Marshal(Uint64(in))
if err != nil {
t.Errorf("%d: %v", in, err)
continue
}
if want := `"` + test.want + `"`; string(out) != want {
t.Errorf("%d: MarshalJSON output mismatch: got %q, want %q", in, out, want)
continue
}
if out := (Uint64)(in).String(); out != test.want {
t.Errorf("%x: String mismatch: got %q, want %q", in, out, test.want)
continue
}
}
}
func TestMarshalUint(t *testing.T) {
for _, test := range encodeUintTests {
in := test.input.(uint)
out, err := json.Marshal(Uint(in))
if err != nil {
t.Errorf("%d: %v", in, err)
continue
}
if want := `"` + test.want + `"`; string(out) != want {
t.Errorf("%d: MarshalJSON output mismatch: got %q, want %q", in, out, want)
continue
}
if out := (Uint)(in).String(); out != test.want {
t.Errorf("%x: String mismatch: got %q, want %q", in, out, test.want)
continue
}
}
}
var (
// These are variables (not constants) to avoid constant overflow
// checks in the compiler on 32bit platforms.
maxUint33bits = uint64(^uint32(0)) + 1
maxUint64bits = ^uint64(0)
)
var unmarshalUintTests = []unmarshalTest{
// invalid encoding
{input: "", wantErr: errJSONEOF},
{input: "null", wantErr: errNonString(uintT)},
{input: "10", wantErr: errNonString(uintT)},
{input: `"0"`, wantErr: wrapTypeError(ErrMissingPrefix, uintT)},
{input: `"0x"`, wantErr: wrapTypeError(ErrEmptyNumber, uintT)},
{input: `"0x01"`, wantErr: wrapTypeError(ErrLeadingZero, uintT)},
{input: `"0x100000000"`, want: uint(maxUint33bits), wantErr32bit: wrapTypeError(ErrUintRange, uintT)},
{input: `"0xfffffffffffffffff"`, wantErr: wrapTypeError(ErrUintRange, uintT)},
{input: `"0xx"`, wantErr: wrapTypeError(ErrSyntax, uintT)},
{input: `"0x1zz01"`, wantErr: wrapTypeError(ErrSyntax, uintT)},
// valid encoding
{input: `""`, want: uint(0)},
{input: `"0x0"`, want: uint(0)},
{input: `"0x2"`, want: uint(0x2)},
{input: `"0x2F2"`, want: uint(0x2f2)},
{input: `"0X2F2"`, want: uint(0x2f2)},
{input: `"0x1122aaff"`, want: uint(0x1122aaff)},
{input: `"0xbbb"`, want: uint(0xbbb)},
{input: `"0xffffffff"`, want: uint(0xffffffff)},
{input: `"0xffffffffffffffff"`, want: uint(maxUint64bits), wantErr32bit: wrapTypeError(ErrUintRange, uintT)},
}
func TestUnmarshalUint(t *testing.T) {
for _, test := range unmarshalUintTests {
var v Uint
err := json.Unmarshal([]byte(test.input), &v)
if uintBits == 32 && test.wantErr32bit != nil {
checkError(t, test.input, err, test.wantErr32bit)
continue
}
if !checkError(t, test.input, err, test.wantErr) {
continue
}
if uint(v) != test.want.(uint) {
t.Errorf("input %s: value mismatch: got %d, want %d", test.input, v, test.want)
continue
}
}
}
func TestUnmarshalFixedUnprefixedText(t *testing.T) {
tests := []struct {
input string
want []byte
wantErr error
}{
{input: "0x2", wantErr: ErrOddLength},
{input: "2", wantErr: ErrOddLength},
{input: "4444", wantErr: errors.New("hex string has length 4, want 8 for x")},
{input: "4444", wantErr: errors.New("hex string has length 4, want 8 for x")},
// check that output is not modified for partially correct input
{input: "444444gg", wantErr: ErrSyntax, want: []byte{0, 0, 0, 0}},
{input: "0x444444gg", wantErr: ErrSyntax, want: []byte{0, 0, 0, 0}},
// valid inputs
{input: "44444444", want: []byte{0x44, 0x44, 0x44, 0x44}},
{input: "0x44444444", want: []byte{0x44, 0x44, 0x44, 0x44}},
}
for _, test := range tests {
out := make([]byte, 4)
err := UnmarshalFixedUnprefixedText("x", []byte(test.input), out)
switch {
case err == nil && test.wantErr != nil:
t.Errorf("%q: got no error, expected %q", test.input, test.wantErr)
case err != nil && test.wantErr == nil:
t.Errorf("%q: unexpected error %q", test.input, err)
case err != nil && err.Error() != test.wantErr.Error():
t.Errorf("%q: error mismatch: got %q, want %q", test.input, err, test.wantErr)
}
if test.want != nil && !bytes.Equal(out, test.want) {
t.Errorf("%q: output mismatch: got %x, want %x", test.input, out, test.want)
}
}
}
package types
import (
"math/big"
)
var (
zero = big.NewInt(0)
)
type BigInt struct {
big.Int
}
func NewBigInt(v int64) *BigInt {
return &BigInt{*big.NewInt(v)}
}
func (b BigInt) GetInt() *big.Int {
return &b.Int
}
func (b BigInt) Marshal() ([]byte, error) {
return b.Bytes(), nil
}
func (b *BigInt) MarshalTo(data []byte) (n int, err error) {
var d = b.Bytes()
if len(d) > len(data) {
copy(data, d[:len(data)])
return len(data), nil
} else {
copy(data, d)
return len(d), nil
}
}
func (b *BigInt) Unmarshal(data []byte) error {
b.Int.SetBytes(data)
return nil
}
func (b *BigInt) Size() int {
return len(b.Int.Bytes())
}
func (b BigInt) MarshalJSON() ([]byte, error) {
return []byte(b.Text(10)), nil
}
func (b *BigInt) UnmarshalJSON(data []byte) error {
b.SetBytes(data)
return nil
}
// only required if the compare option is set
func (b BigInt) Compare(other BigInt) int {
return b.Int.Cmp(&other.Int)
}
// only required if the equal option is set
func (b BigInt) Equal(other BigInt) bool {
return b.Int.Cmp(&other.Int) == 0
}
// only required if populate option is set
// func NewPopulatedT(r randyThetest) *T {}
type randy interface {
Intn(n int) int
}
func NewPopulatedBigInt(r randy) *BigInt {
data := make([]byte, 32)
for i := 0; i < 32; i++ {
data[i] = byte(r.Intn(255))
}
b := new(BigInt)
b.Unmarshal(data)
return b
}
package types
import (
"fmt"
"math/big"
"testing"
)
func TestBigInt(t *testing.T) {
b1000 := big.NewInt(1000)
m := b1000.Bytes()
a := Hash{}
fmt.Printf("init a is %s\n", a.Add(a.GetInt(), big.NewInt(10)))
a.Unmarshal(m)
fmt.Printf("after unmarshal a is %s\n", a.String())
// l, err := a.MarshalTo(m)
// fmt.Printf("marshal to l=%v,err=%v\n", l, err)
// fmt.Printf("after marshal to a = %s\n", a.String())
b := new(Hash)
d, err := a.Marshal()
if err != nil {
fmt.Printf("marshal a get err=%s\n", err)
}
err = b.Unmarshal(d)
if err != nil {
fmt.Printf("unmarshal b get err=%s\n", err)
}
fmt.Printf("b is %s\n", b.String())
fmt.Printf("compare a and b = %v\n", a.Compare(*b))
}
package coretype
import "github.com/CaduceusMetaverseProtocol/MetaTypes/types"
type Account struct {
Addr types.Address `json:"address"`
Nonce uint64 `json:"nonce"`
Balance types.BigInt `json:"balance"`
Root types.Hash `json:"root"`
Code []byte `json:"code"`
CodeHash types.Hash `json:"code_hash"`
}
package types
import (
"bytes"
"database/sql/driver"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"math/big"
"math/rand"
"reflect"
"strings"
"github.com/CaduceusMetaverseProtocol/MetaTypes/tools"
"golang.org/x/crypto/sha3"
)
// Lengths of hashes and addresses in bytes.
const (
// HashLength is the expected length of the hash
HashLength = 32
// AddressLength is the expected length of the address
AddressLength = 20
)
var (
hashT = reflect.TypeOf(Hash{})
addressT = reflect.TypeOf(Address{})
)
// Hash represents the 32 byte Keccak256 hash of arbitrary data.
type Hash [HashLength]byte
// BytesToHash sets b to hash.
// If b is larger than len(h), b will be cropped from the left.
func BytesToHash(b []byte) Hash {
var h Hash
h.SetBytes(b)
return h
}
// BigToHash sets byte representation of b to hash.
// If b is larger than len(h), b will be cropped from the left.
func BigToHash(b *big.Int) Hash { return BytesToHash(b.Bytes()) }
// HexToHash sets byte representation of s to hash.
// If b is larger than len(h), b will be cropped from the left.
func HexToHash(s string) Hash { return BytesToHash(tools.FromHex(s)) }
func (h Hash) Marshal() ([]byte, error) {
return h[:], nil
}
func (h *Hash) MarshalTo(data []byte) (n int, err error) {
if len(h) > len(data) {
copy(data, h[:len(data)])
return len(data), nil
} else {
copy(data, h[:])
return len(h), nil
}
}
func (h *Hash) Unmarshal(data []byte) error {
h.SetBytes(data)
return nil
}
func (h *Hash) Size() int {
return len(h)
}
func (h Hash) MarshalJSON() ([]byte, error) {
return h.MarshalText()
}
//func (h *Hash) UnmarshalJSON(data []byte) error {
// return tools.UnmarshalFixedJSON(hashT, data, h[:])
//}
// only required if the compare option is set
func (h Hash) Compare(other Hash) int {
return bytes.Compare(h[:], other[:])
}
// only required if the equal option is set
func (h Hash) Equal(other Hash) bool {
return bytes.Equal(h[:], other[:])
}
// Bytes gets the byte representation of the underlying hash.
func (h Hash) Bytes() []byte { return h[:] }
// Big converts a hash to a big integer.
func (h Hash) Big() *big.Int { return new(big.Int).SetBytes(h[:]) }
// Hex converts a hash to a hex string.
func (h Hash) Hex() string { return tools.Encode(h[:]) }
// TerminalString implements log.TerminalStringer, formatting a string for console
// output during logging.
func (h Hash) TerminalString() string {
return fmt.Sprintf("%x..%x", h[:3], h[29:])
}
// String implements the stringer interface and is used also by the logger when
// doing full logging into a file.
func (h Hash) String() string {
return h.Hex()
}
// Format implements fmt.Formatter.
// Hash supports the %v, %s, %q, %x, %X and %d format verbs.
func (h Hash) Format(s fmt.State, c rune) {
hexb := make([]byte, 2+len(h)*2)
copy(hexb, "0x")
hex.Encode(hexb[2:], h[:])
switch c {
case 'x', 'X':
if !s.Flag('#') {
hexb = hexb[2:]
}
if c == 'X' {
hexb = bytes.ToUpper(hexb)
}
fallthrough
case 'v', 's':
s.Write(hexb)
case 'q':
q := []byte{'"'}
s.Write(q)
s.Write(hexb)
s.Write(q)
case 'd':
fmt.Fprint(s, ([len(h)]byte)(h))
default:
fmt.Fprintf(s, "%%!%c(hash=%x)", c, h)
}
}
// UnmarshalText parses a hash in hex syntax.
func (h *Hash) UnmarshalText(input []byte) error {
return tools.UnmarshalFixedText("Hash", input, h[:])
}
// UnmarshalJSON parses a hash in hex syntax.
func (h *Hash) UnmarshalJSON(input []byte) error {
return tools.UnmarshalFixedJSON(hashT, input, h[:])
}
// MarshalText returns the hex representation of h.
func (h Hash) MarshalText() ([]byte, error) {
return tools.Bytes(h[:]).MarshalText()
}
// SetBytes sets the hash to the value of b.
// If b is larger than len(h), b will be cropped from the left.
func (h *Hash) SetBytes(b []byte) {
if len(b) > len(h) {
b = b[len(b)-HashLength:]
}
copy(h[HashLength-len(b):], b)
}
// Generate implements testing/quick.Generator.
func (h Hash) Generate(rand *rand.Rand, size int) reflect.Value {
m := rand.Intn(len(h))
for i := len(h) - 1; i > m; i-- {
h[i] = byte(rand.Uint32())
}
return reflect.ValueOf(h)
}
// Scan implements Scanner for database/sql.
func (h *Hash) Scan(src interface{}) error {
srcB, ok := src.([]byte)
if !ok {
return fmt.Errorf("can't scan %T into Hash", src)
}
if len(srcB) != HashLength {
return fmt.Errorf("can't scan []byte of len %d into Hash, want %d", len(srcB), HashLength)
}
copy(h[:], srcB)
return nil
}
// Value implements valuer for database/sql.
func (h Hash) Value() (driver.Value, error) {
return h[:], nil
}
// ImplementsGraphQLType returns true if Hash implements the specified GraphQL type.
func (Hash) ImplementsGraphQLType(name string) bool { return name == "Bytes32" }
// UnmarshalGraphQL unmarshals the provided GraphQL query data.
func (h *Hash) UnmarshalGraphQL(input interface{}) error {
var err error
switch input := input.(type) {
case string:
err = h.UnmarshalText([]byte(input))
default:
err = fmt.Errorf("unexpected type %T for Hash", input)
}
return err
}
// UnprefixedHash allows marshaling a Hash without 0x prefix.
type UnprefixedHash Hash
// UnmarshalText decodes the hash from hex. The 0x prefix is optional.
func (h *UnprefixedHash) UnmarshalText(input []byte) error {
return tools.UnmarshalFixedUnprefixedText("UnprefixedHash", input, h[:])
}
// MarshalText encodes the hash as hex.
func (h UnprefixedHash) MarshalText() ([]byte, error) {
return []byte(hex.EncodeToString(h[:])), nil
}
/////////// Address
// Address represents the 20 byte address of an Ethereum account.
type Address [AddressLength]byte
type Addresses []Address
func (as *Addresses) MarshalJSON() ([]byte, error) {
asBytes := make([][]byte, 0, len(*as))
for _, addr := range *as {
aAsJson, err := addr.Marshal()
if err != nil {
return nil, err
}
asBytes = append(asBytes, aAsJson)
}
return json.Marshal(asBytes)
}
func (as *Addresses) UnmarshalJSON(b []byte) error {
addrsAsBytes := make([][]byte, 0)
if err := json.Unmarshal(b, &addrsAsBytes); err != nil {
return err
}
for _, addrBytes := range addrsAsBytes {
addr := &Address{}
if addrBytes != nil {
if err := addr.Unmarshal(addrBytes); err != nil {
return err
}
} else {
}
*as = append(*as, *addr)
}
return nil
}
// BytesToAddress returns Address with value b.
// If b is larger than len(h), b will be cropped from the left.
func BytesToAddress(b []byte) Address {
var a Address
a.SetBytes(b)
return a
}
// BigToAddress returns Address with byte values of b.
// If b is larger than len(h), b will be cropped from the left.
func BigToAddress(b *big.Int) Address { return BytesToAddress(b.Bytes()) }
// HexToAddress returns Address with byte values of s.
// If s is larger than len(h), s will be cropped from the left.
func HexToAddress(s string) Address { return BytesToAddress(tools.FromHex(s)) }
// IsHexAddress verifies whether a string can represent a valid hex-encoded
// Ethereum address or not.
func IsHexAddress(s string) bool {
if tools.Has0xPrefix(s) {
s = s[2:]
}
return len(s) == 2*AddressLength && tools.IsHex(s)
}
func (a Address) Marshal() ([]byte, error) {
return a[:], nil
}
func (a *Address) MarshalTo(data []byte) (n int, err error) {
if len(a) > len(data) {
copy(data, a[:len(data)])
return len(data), nil
} else {
copy(data, a[:])
return len(a), nil
}
}
func (a *Address) Unmarshal(data []byte) error {
a.SetBytes(data)
return nil
}
func (a *Address) Size() int {
return len(a)
}
func (a Address) MarshalJSON() ([]byte, error) {
return a.MarshalText()
}
//func (a *Address) UnmarshalJSON(data []byte) error {
//}
// only required if the compare option is set
func (a Address) Compare(other Address) int {
return bytes.Compare(a[:], other[:])
}
// only required if the equal option is set
func (a Address) Equal(other Address) bool {
return bytes.Equal(a[:], other[:])
}
// Bytes gets the string representation of the underlying address.
func (a Address) Bytes() []byte { return a[:] }
// Hash converts an address to a hash by left-padding it with zeros.
func (a Address) Hash() Hash { return BytesToHash(a[:]) }
// Hex returns an EIP55-compliant hex string representation of the address.
func (a Address) Hex() string {
return string(a.checksumHex())
}
// String implements fmt.Stringer.
func (a Address) String() string {
return a.Hex()
}
func (a *Address) checksumHex() []byte {
buf := a.hex()
// compute checksum
sha := sha3.NewLegacyKeccak256()
sha.Write(buf[2:])
hash := sha.Sum(nil)
for i := 2; i < len(buf); i++ {
hashByte := hash[(i-2)/2]
if i%2 == 0 {
hashByte = hashByte >> 4
} else {
hashByte &= 0xf
}
if buf[i] > '9' && hashByte > 7 {
buf[i] -= 32
}
}
return buf[:]
}
func (a Address) hex() []byte {
var buf [len(a)*2 + 2]byte
copy(buf[:2], "0x")
hex.Encode(buf[2:], a[:])
return buf[:]
}
// Format implements fmt.Formatter.
// Address supports the %v, %s, %q, %x, %X and %d format verbs.
func (a Address) Format(s fmt.State, c rune) {
switch c {
case 'v', 's':
s.Write(a.checksumHex())
case 'q':
q := []byte{'"'}
s.Write(q)
s.Write(a.checksumHex())
s.Write(q)
case 'x', 'X':
// %x disables the checksum.
hex := a.hex()
if !s.Flag('#') {
hex = hex[2:]
}
if c == 'X' {
hex = bytes.ToUpper(hex)
}
s.Write(hex)
case 'd':
fmt.Fprint(s, ([len(a)]byte)(a))
default:
fmt.Fprintf(s, "%%!%c(address=%x)", c, a)
}
}
// SetBytes sets the address to the value of b.
// If b is larger than len(a), b will be cropped from the left.
func (a *Address) SetBytes(b []byte) {
if len(b) > len(a) {
b = b[len(b)-AddressLength:]
}
copy(a[AddressLength-len(b):], b)
}
// MarshalText returns the hex representation of a.
func (a Address) MarshalText() ([]byte, error) {
return tools.Bytes(a[:]).MarshalText()
}
// UnmarshalText parses a hash in hex syntax.
func (a *Address) UnmarshalText(input []byte) error {
return tools.UnmarshalFixedText("Address", input, a[:])
}
// UnmarshalJSON parses a hash in hex syntax.
func (a *Address) UnmarshalJSON(input []byte) error {
return tools.UnmarshalFixedJSON(addressT, input, a[:])
}
// Scan implements Scanner for database/sql.
func (a *Address) Scan(src interface{}) error {
srcB, ok := src.([]byte)
if !ok {
return fmt.Errorf("can't scan %T into Address", src)
}
if len(srcB) != AddressLength {
return fmt.Errorf("can't scan []byte of len %d into Address, want %d", len(srcB), AddressLength)
}
copy(a[:], srcB)
return nil
}
// Value implements valuer for database/sql.
func (a Address) Value() (driver.Value, error) {
return a[:], nil
}
// ImplementsGraphQLType returns true if Hash implements the specified GraphQL type.
func (a Address) ImplementsGraphQLType(name string) bool { return name == "Address" }
// UnmarshalGraphQL unmarshals the provided GraphQL query data.
func (a *Address) UnmarshalGraphQL(input interface{}) error {
var err error
switch input := input.(type) {
case string:
err = a.UnmarshalText([]byte(input))
default:
err = fmt.Errorf("unexpected type %T for Address", input)
}
return err
}
// UnprefixedAddress allows marshaling an Address without 0x prefix.
type UnprefixedAddress Address
// UnmarshalText decodes the address from hex. The 0x prefix is optional.
func (a *UnprefixedAddress) UnmarshalText(input []byte) error {
return tools.UnmarshalFixedUnprefixedText("UnprefixedAddress", input, a[:])
}
// MarshalText encodes the address as hex.
func (a UnprefixedAddress) MarshalText() ([]byte, error) {
return []byte(hex.EncodeToString(a[:])), nil
}
// MixedcaseAddress retains the original string, which may or may not be
// correctly checksummed
type MixedcaseAddress struct {
addr Address
original string
}
// NewMixedcaseAddress constructor (mainly for testing)
func NewMixedcaseAddress(addr Address) MixedcaseAddress {
return MixedcaseAddress{addr: addr, original: addr.Hex()}
}
// NewMixedcaseAddressFromString is mainly meant for unit-testing
func NewMixedcaseAddressFromString(hexaddr string) (*MixedcaseAddress, error) {
if !IsHexAddress(hexaddr) {
return nil, errors.New("invalid address")
}
a := tools.FromHex(hexaddr)
return &MixedcaseAddress{addr: BytesToAddress(a), original: hexaddr}, nil
}
// UnmarshalJSON parses MixedcaseAddress
func (ma *MixedcaseAddress) UnmarshalJSON(input []byte) error {
if err := tools.UnmarshalFixedJSON(addressT, input, ma.addr[:]); err != nil {
return err
}
return json.Unmarshal(input, &ma.original)
}
// MarshalJSON marshals the original value
func (ma *MixedcaseAddress) MarshalJSON() ([]byte, error) {
if strings.HasPrefix(ma.original, "0x") || strings.HasPrefix(ma.original, "0X") {
return json.Marshal(fmt.Sprintf("0x%s", ma.original[2:]))
}
return json.Marshal(fmt.Sprintf("0x%s", ma.original))
}
// Address returns the address
func (ma *MixedcaseAddress) Address() Address {
return ma.addr
}
// String implements fmt.Stringer
func (ma *MixedcaseAddress) String() string {
if ma.ValidChecksum() {
return fmt.Sprintf("%s [chksum ok]", ma.original)
}
return fmt.Sprintf("%s [chksum INVALID]", ma.original)
}
// ValidChecksum returns true if the address has valid checksum
func (ma *MixedcaseAddress) ValidChecksum() bool {
return ma.original == ma.addr.Hex()
}
// Original returns the mixed-case input string
func (ma *MixedcaseAddress) Original() string {
return ma.original
}
......@@ -50,7 +50,7 @@ require (
)
replace (
github.com/CaduceusMetaverseProtocol/MetaCryptor => ../MetaCryptor-main
github.com/CaduceusMetaverseProtocol/MetaProtocol => ../MetaProtocol-main
github.com/CaduceusMetaverseProtocol/MetaTypes => ../MetaTypes-main
github.com/CaduceusMetaverseProtocol/MetaCryptor => ./MetaCryptor-main
github.com/CaduceusMetaverseProtocol/MetaProtocol => ./MetaProtocol-main
github.com/CaduceusMetaverseProtocol/MetaTypes => ./MetaTypes-main
)
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