新注册的用户请输入邮箱并保存,随后登录邮箱激活账号。后续可直接使用邮箱登录!

Commit f8a3b72e authored by taifu's avatar taifu

Merge branch 'v1.2.0_qc_ut' into 'v1.2.0_qc' (merge request !2)

v1.2.0_qc_ut
parents a8d35d9d 2475b9b4
No related merge requests found
# 完整版本在 https://golangci-lint.run/usage/configuration/
linters-settings:
funlen:
lines: 80
statements: 80
goconst:
min-len: 2
min-occurrences: 2
gocyclo:
min-complexity: 20
goimports:
#local-prefixes: git.code.oa.com,git.woa.com
revive:
confidence: 0
rules:
- name: var-declaration
- name: package-comments
- name: dot-imports
- name: blank-imports
- name: exported
# - name: var-naming
- name: indent-error-flow
- name: range
- name: errorf
- name: error-naming
- name: error-strings
# - name: receiver-naming
- name: increment-decrement
- name: error-return
#- name: unexported-return
- name: time-naming
- name: context-keys-type
- name: context-as-argument
govet:
enable:
- shadow
lll:
line-length: 120
errcheck:
check-type-assertions: true
gocritic:
enabled-checks:
- nestingReduce
settings:
nestingReduce:
bodyWidth: 5
linters:
disable-all: true
enable:
- funlen
- goconst
- gocyclo
- gofmt
- ineffassign
- staticcheck
- typecheck
- goimports
- revive
- gosimple
- govet
- lll
- rowserrcheck
- errcheck
- unused
- sqlclosecheck
# - gocritic
# - bodyclose https://github.com/timakin/bodyclose/issues 问题太多了,屏蔽都屏蔽不过来,显式不使用它
run:
timeout: 20m
issues:
exclude-use-default: true
# The list of ids of default excludes to include or disable. By default it's empty.
# 下面的规则,golangci-lint认为应该屏蔽,但是我们选择不屏蔽。所以,`exclude-use-default: true`屏蔽一部分,把下面的再捞出来。
# golanglint-ci维护的忽略列表里有一些是我们不想屏蔽的,捞出来。这里说一下,使用白名单是好于黑名单的。名单随着golanglint-ci引入更多工具,我们跟进享受好处。我们搞黑名单,就变成自己维护,不如golanglint-ci去维护,更好。
include:
- EXC0004 # govet (possible misuse of unsafe.Pointer|should have signature)
- EXC0005 # staticcheck ineffective break statement. Did you mean to break out of the outer loop
- EXC0012 # revive exported (method|function|type|const) (.+) should have comment or be unexported
- EXC0013 # revive package comment should be of the form "(.+)...
- EXC0014 # revive comment on exported (.+) should be of the form "(.+)..."
- EXC0015 # revive should have a package comment, unless it's in another file for this package
exclude-rules:
- path: _test\.go
linters:
- funlen # 规范说单测函数,单个函数可以到160行,但是工具不好做区分处理,这里就直接不检查单测的函数长度
- linters:
- staticcheck
text: "SA6002: argument should be pointer-like to avoid allocations" # sync.pool.Put(buf), slice `var buf []byte` will tiger this
- linters:
- lll
source: "^//go:generate " # Exclude lll issues for long lines with go:generate
max-same-issues: 0
new: false
max-issues-per-linter: 0
output:
sort-results: true
......@@ -14,7 +14,8 @@ build:
#go build -o did-sync
ut:
echo "ut"
go test -coverprofile cover.out ./...
go tool cover -func=cover.out | tail -1 | grep -P "\\d+\\.\\d+(?=\\%)" -o
lint:
golangci-lint run ./...
......@@ -35,8 +36,8 @@ docker-stop:
docker-compose -f docker-compose.yml down
docker-push:
docker image tag did-sync:${VERSION} hub-dev.cnbn.org.cn:17754/opennet/did-sync:${VERSION}
docker push hub-dev.cnbn.org.cn:17754/opennet/did-sync:${VERSION}
docker image tag did-sync:${VERSION} hub-dev.cnbn.org.cn/opennet/did-sync:${VERSION}
docker push hub-dev.cnbn.org.cn/opennet/did-sync:${VERSION}
docker image tag did-sync:${VERSION} chainmaker1.tencentcloudcr.com/opennet/did-sync:${VERSION}
docker push chainmaker1.tencentcloudcr.com/opennet/did-sync:${VERSION}
......
......@@ -4,10 +4,9 @@
## DID合约
主链DID合约在:
https://git.code.tencent.com/ChainMaker/opennet/contracts/contracts-go/tree/v1.2.0_qc/standard-did
主链DID合约在:https://git.code.tencent.com/ChainMaker/opennet/contracts/contracts-go/tree/v1.2.0_qc/standard-did
子链DID同步合约在:https://git.code.tencent.com/ChainMaker/opennet/contracts/contracts-go/tree/v0.5.0_subchain/standard-did
子链DID同步合约在:https://git.code.tencent.com/ChainMaker/opennet/contracts/contracts-go/tree/v1.2.0_subchain/standard-did
请将以上两个合约安装到对应的ChainMaker链上。
......
// Copyright (C) BABEC. All rights reserved.
// Copyright (C) THL A29 Limited, a Tencent company. All rights reserved.
//
// SPDX-License-Identifier: Apache-2.0
package common
import (
"gorm.io/gorm"
)
var (
//mysqlDB = &gorm.DB{}
dbc = &DbStruct{}
)
// DbStruct 数据库
type DbStruct struct {
db *gorm.DB
}
// InitDbStruct 初始化数据库
func InitDbStruct(db *gorm.DB) {
dbc.db = db
}
// GetDbStruct 获取数据库
func GetDbStruct() *DbStruct {
return dbc
}
// Query 查询
func (d *DbStruct) Query(dst interface{}, orderer string, where interface{}, args ...interface{}) *gorm.DB {
var tx *gorm.DB
if where == nil {
// 表示查询所有
tx = d.db.Find(dst)
if orderer != "" {
tx = d.db.Order(orderer)
}
} else {
// 按照条件查询
tx = d.db.Where(where, args...).Find(dst)
if orderer != "" {
tx = d.db.Order(orderer)
}
}
return tx
}
// QueryLimit 条件查询
func (d *DbStruct) QueryLimit(dst interface{}, orderer string, offset,
limit int, where interface{}, count *int64, args ...interface{}) *gorm.DB {
tx := d.db.Debug()
if orderer != "" {
tx = d.db.Order(orderer)
}
if where == nil {
// 表示查询所有
tx = tx.Offset(offset).Limit(limit).
Find(dst).Limit(-1).Offset(-1).Count(count)
} else {
// 按照条件查询
tx = tx.Debug().Where(where, args...).Offset(offset).Limit(limit).
Find(dst).Limit(-1).Offset(-1).Count(count)
}
return tx
}
// QueryCount 查询数据条数
func (d *DbStruct) QueryCount(tableName string, where interface{}, args ...interface{}) int64 {
var instanceNum int64
d.db.Table(tableName).Where(where, args).Count(&instanceNum)
return instanceNum
}
// GetDb 获取DB
func (d *DbStruct) GetDb() *gorm.DB {
return d.db
}
// QueryFirst 查询最新数据
func (d *DbStruct) QueryFirst(dst interface{}, where interface{}, args ...interface{}) *gorm.DB {
var tx *gorm.DB
if where == nil {
// 表示查询所有
tx = d.db.First(dst)
} else {
// 按照条件查询
tx = d.db.Where(where, args...).First(dst)
}
return tx
}
// Create 创建
func (d *DbStruct) Create(m interface{}) *gorm.DB {
return d.db.Create(m)
}
// Save update if info is existed
func (d *DbStruct) Save(m interface{}) *gorm.DB {
return d.db.Save(m)
}
// Update 更新数据
func (d *DbStruct) Update(m interface{}, where interface{}, args ...interface{}) *gorm.DB {
var tx *gorm.DB
if where == nil {
// 表示更新所有
tx = d.db.Updates(m)
} else {
// 按照条件更新
tx = d.db.Model(m).Where(where, args).Updates(m)
}
return tx
}
// Delete 删除
func (d *DbStruct) Delete(m interface{}, where interface{}, args ...interface{}) *gorm.DB {
// 表示删除所有
return d.db.Where(where, args).Delete(m)
}
// Copyright (C) BABEC. All rights reserved.
// Copyright (C) THL A29 Limited, a Tencent company. All rights reserved.
//
// SPDX-License-Identifier: Apache-2.0
package common
import (
"errors"
"os"
)
// PathExists 文件或目录是否存在
func PathExists(path string) (bool, error) {
fi, err := os.Stat(path)
if err == nil {
if fi.IsDir() {
return true, nil
}
return false, errors.New("存在同名文件")
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
// FileExists 文件或目录是否存在
func FileExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
// CreateDir 批量创建文件夹
func CreateDir(dirs ...string) error {
for _, v := range dirs {
exist, err := PathExists(v)
if err != nil {
return err
}
if !exist {
if err = os.MkdirAll(v, os.ModePerm); err != nil {
return err
}
}
}
return nil
}
// IsExist determines whether the file spcified by the given path is exists.
func IsExist(path string) bool {
_, err := os.Stat(path)
return err == nil || os.IsExist(err)
}
// IsDir determines whether the specified path is a directory.
func IsDir(path string) bool {
fio, err := os.Lstat(path)
if os.IsNotExist(err) {
return false
}
if nil != err {
return false
}
return fio.IsDir()
}
......@@ -49,6 +49,7 @@ func Viper(path ...string) *viper.Viper {
fmt.Println(err)
}
// 监听配置修改
v.WatchConfig()
v.OnConfigChange(func(e fsnotify.Event) {
fmt.Println("config file changed:", e.Name)
......
......@@ -42,6 +42,7 @@ func NewSyncHandle(ctx context.Context, errorC chan error) (*SyncHandle, error)
var startBlock int64
// 从子链 同步合约 获取区块高度
for {
// 调用同步合约,若调用失败(子链未正常运行)则五分钟后重试
resp, err := initialize.SubSdkClient.SdkClient.QueryContract(contractName, getBlockHeight, nil, -1)
if err != nil {
global.LOG.Errorf("The Client failed to query the contract: %s", err)
......@@ -59,7 +60,7 @@ func NewSyncHandle(ctx context.Context, errorC chan error) (*SyncHandle, error)
// 从数据库查询
state, err := sqlite.GetState(global.CONFIG.SubCmSdk.ChainConfig.ChainId)
if err != nil && err.Error() == "record not found" {
state, err = initState(global.CONFIG.EventContract.StartHeight)
state, _ = initState(global.CONFIG.EventContract.StartHeight)
} else if err != nil {
return nil, err
}
......@@ -80,6 +81,7 @@ func NewSyncHandle(ctx context.Context, errorC chan error) (*SyncHandle, error)
global.LOG.Info(fmt.Sprintf("sync start height in config is: %d", startBlock))
}
// 获取监听 event 的 Topic
validTopic := map[string]struct{}{}
for _, topic := range global.CONFIG.EventContract.Topic {
validTopic[topic] = struct{}{}
......
// Copyright (C) BABEC. All rights reserved.
// Copyright (C) THL A29 Limited, a Tencent company. All rights reserved.
//
// SPDX-License-Identifier: Apache-2.0
// Package core 核心逻辑
package core
import (
"context"
sql2 "database/sql"
"errors"
"testing"
"chainmaker.org/chainmaker/pb-go/v2/common"
sdkmock "chainmaker.org/chainmaker/sdk-go/v2/mock"
"chainweaver.org.cn/chainweaver/did/did-sync/db/sqlite"
"chainweaver.org.cn/chainweaver/did/did-sync/global"
"chainweaver.org.cn/chainweaver/did/did-sync/initialize"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"go.uber.org/zap/zaptest"
sql "gorm.io/driver/sqlite"
"gorm.io/gorm"
)
func TestNewSyncHandle(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
// 设置日志
global.LOG = zaptest.NewLogger(t).Sugar()
type test struct {
name string
queryReturn *common.TxResponse
dbState *sqlite.State
dbError error
configStartHeight int64
configEndHeight int64
configTopics []string
expectedStartBlock int64
expectedErr bool
}
tests := []test{
{
name: "Success",
queryReturn: &common.TxResponse{
Code: common.TxStatusCode_SUCCESS,
ContractResult: &common.ContractResult{Result: []byte("10")},
},
dbState: &sqlite.State{SyncHeight: 10},
dbError: nil,
configStartHeight: 5,
configEndHeight: 50,
configTopics: []string{"topic1", "topic2"},
expectedStartBlock: 10,
expectedErr: false,
},
{
name: "QueryContractError",
queryReturn: &common.TxResponse{Code: common.TxStatusCode_CONTRACT_FAIL},
configStartHeight: 5,
expectedStartBlock: 0,
expectedErr: false,
},
{
name: "SQLiteError",
queryReturn: &common.TxResponse{
Code: common.TxStatusCode_SUCCESS,
ContractResult: &common.ContractResult{Result: []byte("10")},
},
dbError: errors.New("db error"),
configStartHeight: 5,
expectedStartBlock: 0,
expectedErr: true,
},
{
name: "InitState",
queryReturn: &common.TxResponse{
Code: common.TxStatusCode_SUCCESS,
ContractResult: &common.ContractResult{Result: []byte("10")},
},
dbError: errors.New("record not found"),
configStartHeight: 5,
expectedStartBlock: 5,
expectedErr: false,
},
{
name: "ConfigStartHeightGreater",
queryReturn: &common.TxResponse{
Code: common.TxStatusCode_SUCCESS,
ContractResult: &common.ContractResult{Result: []byte("5")},
},
dbState: &sqlite.State{SyncHeight: 3},
configStartHeight: 7,
expectedStartBlock: 7,
expectedErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
errorChannel := make(chan error)
mockClient := sdkmock.NewMockSDKInterface(ctrl)
// Mock QueryContract
mockClient.EXPECT().QueryContract(gomock.Any(), getBlockHeight, gomock.Any(), gomock.Any()).Return(
tt.queryReturn, nil).Times(1)
initialize.SubSdkClient.SdkClient = mockClient
global.GVA_DB, _ = gorm.Open(sql.Open("file::memory:?cache=shared"),
&gorm.Config{SkipDefaultTransaction: true})
if tt.name != "SQLiteError" {
// 创建测试所需的表
err := global.GVA_DB.AutoMigrate(&sqlite.State{})
assert.NoError(t, err)
}
db, _ := global.GVA_DB.DB()
defer func(db *sql2.DB) {
err := db.Close()
if err != nil {
t.Logf("Failed to close db: %v", err)
}
}(db)
if tt.dbState != nil {
global.GVA_DB.Create(tt.dbState)
}
// 模拟 Config
global.CONFIG.EventContract.StartHeight = tt.configStartHeight
global.CONFIG.EventContract.EndHeight = tt.configEndHeight
global.CONFIG.EventContract.Topic = tt.configTopics
_, err := NewSyncHandle(ctx, errorChannel)
if tt.expectedErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}
func TestSyncHandle_StartSync(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockClient := sdkmock.NewMockSDKInterface(ctrl)
initialize.SubSdkClient.SdkClient = mockClient
initialize.MainSdkClient.SdkClient = mockClient
global.LOG = zaptest.NewLogger(t).Sugar()
ctx := context.Background()
errorChannel := make(chan error)
// Mock QueryContract
mockClient.EXPECT().QueryContract(gomock.Any(), getBlockHeight, gomock.Any(), gomock.Any()).Return(
&common.TxResponse{
Code: common.TxStatusCode_SUCCESS,
ContractResult: &common.ContractResult{Result: []byte("10")},
}, nil).Times(1)
// Mock SubscribeBlock ,测试是否正确设置起止高度
mockClient.EXPECT().SubscribeBlock(gomock.Any(), int64(10), int64(100), false, false).
Return(nil, nil).Times(1)
global.GVA_DB, _ = gorm.Open(sql.Open("file::memory:?cache=shared"),
&gorm.Config{SkipDefaultTransaction: true})
err := global.GVA_DB.AutoMigrate(&sqlite.State{})
assert.NoError(t, err)
db, _ := global.GVA_DB.DB()
defer func(db *sql2.DB) {
err = db.Close()
if err != nil {
t.Logf("Failed to close db: %v", err)
}
}(db)
global.CONFIG.EventContract.StartHeight = 0
global.CONFIG.EventContract.EndHeight = 100
syncHandle, err := NewSyncHandle(ctx, errorChannel)
assert.NoError(t, err, "Expected no error creating sync handle")
err = syncHandle.StartSync()
assert.NoError(t, err, "Expected no error starting sync handle")
}
......@@ -64,6 +64,7 @@ func (e *BlockHandler) loop(ctx context.Context, eventChan chan *com.BlockEvent)
return
}
// 获取订阅事件
events, err := e.getValidEvents(block)
if err != nil {
global.LOG.Error(fmt.Sprintf("get valid events err[%s]", err))
......@@ -75,8 +76,10 @@ func (e *BlockHandler) loop(ctx context.Context, eventChan chan *com.BlockEvent)
eventChan <- &com.BlockEvent{Height: block.Block.Header.BlockHeight, Events: events}
}
// 订阅区块数达到100次,手动更新同步区块高度
num++
if num == 100 {
// 设置的同步区块高度为本次区块高度-1,防止本次区块无法同步
str := strconv.FormatUint(block.Block.Header.BlockHeight-1, 10)
setBlockHeightKv := []*common.KeyValuePair{
{
......@@ -88,12 +91,9 @@ func (e *BlockHandler) loop(ctx context.Context, eventChan chan *com.BlockEvent)
global.CONFIG.SubCmSdk.ContractName, setBlockHeight, setBlockHeightKv)
resp, err := initialize.SubSdkClient.SdkClient.InvokeContract(
global.CONFIG.SubCmSdk.ContractName, setBlockHeight, "", setBlockHeightKv, -1, true)
if err != nil {
return
}
if resp.Code != common.TxStatusCode_SUCCESS {
return
// 不进行重试
if err != nil || resp.Code != common.TxStatusCode_SUCCESS {
continue
}
global.LOG.Infof("invoke contract success, resp: [code:%d]/[msg:%s]/"+
......@@ -110,23 +110,27 @@ func (e *BlockHandler) loop(ctx context.Context, eventChan chan *com.BlockEvent)
func (e *BlockHandler) getValidEvents(block *common.BlockInfo) ([][]*common.ContractEvent, error) {
events := make(map[int][]*common.ContractEvent)
var resultEvent [][]*common.ContractEvent
// 处理区块中的交易事件,只同步成功的
for i, tx := range block.Block.Txs {
if tx.Result.Code == common.TxStatusCode_SUCCESS {
events[i] = tx.Result.ContractResult.ContractEvent
}
}
// 根据 DAG 确定事件顺序
txIndexBatch, dagRemain, reverseDagRemain, err := initSimulateDag(block.Block.Dag)
if err != nil {
return nil, err
}
for _, i := range txIndexBatch {
for i := 0; i < len(txIndexBatch); i++ {
index := txIndexBatch[i]
var validEvents []*common.ContractEvent
if events[i] == nil {
if events[index] == nil {
continue
}
for _, event := range events[i] {
for _, event := range events[index] {
// 过滤事件
if event.ContractName == global.CONFIG.EventContract.Name {
if len(e.validTopic) == 0 {
validEvents = append(validEvents, event)
......@@ -138,7 +142,7 @@ func (e *BlockHandler) getValidEvents(block *common.BlockInfo) ([][]*common.Cont
if len(validEvents) != 0 {
resultEvent = append(resultEvent, validEvents)
}
txIndexBatch = append(txIndexBatch, shrinkDag(i, dagRemain, reverseDagRemain)...)
txIndexBatch = append(txIndexBatch, shrinkDag(index, dagRemain, reverseDagRemain)...)
}
return resultEvent, nil
......
......@@ -7,72 +7,244 @@ package handle
import (
"context"
"encoding/json"
"fmt"
"os"
"testing"
"time"
"chainmaker.org/chainmaker/pb-go/v2/common"
sdkmock "chainmaker.org/chainmaker/sdk-go/v2/mock"
com "chainweaver.org.cn/chainweaver/did/did-sync/common"
"chainweaver.org.cn/chainweaver/did/did-sync/core/listen"
"chainweaver.org.cn/chainweaver/did/did-sync/global"
"chainweaver.org.cn/chainweaver/did/did-sync/initialize"
"github.com/stretchr/testify/require"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"go.uber.org/zap/zaptest"
)
func TestSdk(t *testing.T) {
global.GVA_VP = com.Viper("../../etc_test/config.yaml") // 初始化Viper
global.LOG = initialize.Zap(global.CONFIG.Zap)
// createTestBlockInfo 创建 BlockInfo 对象
func createTestBlockInfo(height uint64, txs []*common.Transaction, dag *common.DAG) *common.BlockInfo {
return &common.BlockInfo{
Block: &common.Block{
Header: &common.BlockHeader{
BlockHeight: height,
},
Txs: txs,
Dag: dag,
},
}
}
client := initialize.InitSdk(global.CONFIG.MainCmSdk, false, global.LOG)
// createTestTransaction 创建 Transaction 对象
func createTestTransaction(code common.TxStatusCode, events []*common.ContractEvent) *common.Transaction {
return &common.Transaction{
Result: &common.Result{
Code: code,
ContractResult: &common.ContractResult{
ContractEvent: events,
},
},
}
}
height := uint64(46991)
block, err := client.GetBlockByHeight(height, false)
require.Nil(t, err)
// createTestContractEvent 创建 ContractEvent 对象
func createTestContractEvent(contractName, topic string) *common.ContractEvent {
return &common.ContractEvent{
ContractName: contractName,
Topic: topic,
}
}
e := NewBlockHandler(nil, nil, nil)
// createTestDAG 辅助函数,用于创建 DAG 对象
func createTestDAG(vertexes [][]uint32) *common.DAG {
if len(vertexes) == 0 {
return &common.DAG{Vertexes: []*common.DAG_Neighbor{
{Neighbors: make([]uint32, 0)},
}}
}
var dagVertexes = make([]*common.DAG_Neighbor, len(vertexes))
for i, neighbors := range vertexes {
dagVertexes[i] = &common.DAG_Neighbor{Neighbors: neighbors}
}
return &common.DAG{Vertexes: dagVertexes}
}
events, err := e.getValidEvents(block)
require.Nil(t, err)
var (
mockCtrl *gomock.Controller
mockClient *sdkmock.MockSDKInterface
errorChannel = make(chan error)
)
fmt.Printf("events %+v\n", events)
// TestMain将在所有测试之前运行
func TestMain(m *testing.M) {
global.CONFIG.EventContract.Name = "Contract"
var eventList []*common.ContractEvent
for _, list := range events {
eventList = append(eventList, list...)
}
mockCtrl = gomock.NewController(nil) // 初始化 gomock 控制器
mockClient = sdkmock.NewMockSDKInterface(mockCtrl)
eventsByte, err := json.Marshal(eventList)
if err != nil {
require.Nil(t, err)
}
initialize.SubSdkClient.SdkClient = mockClient
fmt.Printf("events string %s\n", eventsByte)
// 执行测试
exitVal := m.Run()
// 这里可以进行全局清理,如果有的话
mockCtrl.Finish()
// 退出,返回测试结果状态码
os.Exit(exitVal)
}
func TestBlockHandler(t *testing.T) {
global.GVA_VP = com.Viper("../../etc_test/config.yaml") // 初始化Viper
global.LOG = initialize.Zap(global.CONFIG.Zap)
func TestBlockHandler_getValidEvents(t *testing.T) {
validTopic := map[string]struct{}{
"ValidTopic1": {},
"ValidTopic2": {},
}
global.LOG = zaptest.NewLogger(t).Sugar()
tests := []struct {
name string
blockInfo *common.BlockInfo
expectedEvents int
expectedError bool
}{
{
name: "NoTxs",
blockInfo: createTestBlockInfo(1, []*common.Transaction{}, createTestDAG(nil)),
expectedEvents: 0,
expectedError: false,
},
{
name: "NoSuccessTxs",
blockInfo: createTestBlockInfo(1, []*common.Transaction{
createTestTransaction(common.TxStatusCode_CONTRACT_FAIL, []*common.ContractEvent{
createTestContractEvent("Contract", "Topic"),
}),
}, createTestDAG(nil)),
expectedEvents: 0,
expectedError: false,
},
{
name: "NoValidEvents",
blockInfo: createTestBlockInfo(1, []*common.Transaction{
createTestTransaction(common.TxStatusCode_SUCCESS, []*common.ContractEvent{
createTestContractEvent("Contract", "InvalidTopic"),
}),
}, createTestDAG(nil)),
expectedEvents: 0,
expectedError: false,
},
{
name: "ValidEvents",
blockInfo: createTestBlockInfo(1, []*common.Transaction{
createTestTransaction(common.TxStatusCode_SUCCESS, []*common.ContractEvent{
createTestContractEvent("Contract", "ValidTopic1"),
}),
}, createTestDAG(nil)),
expectedEvents: 1,
expectedError: false,
},
{
name: "DagError",
blockInfo: createTestBlockInfo(1, []*common.Transaction{}, createTestDAG([][]uint32{
0: {1},
1: {0}, // Circular dependency to trigger DAG error
})),
expectedEvents: 0,
expectedError: true,
},
{
name: "DagProcessing",
blockInfo: createTestBlockInfo(1, []*common.Transaction{
createTestTransaction(common.TxStatusCode_SUCCESS, []*common.ContractEvent{
createTestContractEvent("Contract", "ValidTopic1"),
}),
createTestTransaction(common.TxStatusCode_SUCCESS, []*common.ContractEvent{
createTestContractEvent("Contract", "ValidTopic2"),
}),
}, createTestDAG([][]uint32{
0: {},
1: {0},
})),
expectedEvents: 2,
expectedError: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
blockHandler := NewBlockHandler(nil, validTopic, errorChannel)
events, err := blockHandler.getValidEvents(tt.blockInfo)
if tt.expectedError {
assert.Error(t, err)
assert.Nil(t, events)
} else {
assert.NoError(t, err)
assert.Equal(t, tt.expectedEvents, len(events))
}
})
}
}
initialize.InitSdk(global.CONFIG.MainCmSdk, false, global.LOG)
initialize.InitSdk(global.CONFIG.SubCmSdk, true, global.LOG)
func TestBlockHandler_loopWithInvalid(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
listener := listen.NewEventListener(int64(70120), -1, nil)
handler := NewBlockHandler(listener.BlockChan, nil, nil)
global.LOG = zaptest.NewLogger(t).Sugar()
ctx := context.Background()
mockClient.EXPECT().InvokeContract(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(),
gomock.Any()).Return(&common.TxResponse{Code: common.TxStatusCode_SUCCESS}, nil).Times(1)
err := listener.Start(ctx)
if err != nil {
require.Nil(t, err)
blockChannel := make(chan *common.BlockInfo, 1)
eventChannel := make(chan *com.BlockEvent)
validTopic := map[string]struct{}{
"ValidTopic": {},
}
handler.Start(ctx)
event := <-handler.EventChan
eventInfo, err := json.Marshal(event)
if err != nil {
require.Nil(t, err)
blockHandler := NewBlockHandler(blockChannel, validTopic, errorChannel)
go blockHandler.loop(ctx, eventChannel)
for i := 0; i < 101; i++ {
blockInfo := createTestBlockInfo(uint64(i), []*common.Transaction{
createTestTransaction(common.TxStatusCode_SUCCESS, []*common.ContractEvent{
createTestContractEvent("Contract1", "ValidTopic"),
}),
}, createTestDAG(nil))
blockChannel <- blockInfo
}
fmt.Printf("Event %s\n", string(eventInfo))
cancel()
time.Sleep(50 * time.Millisecond)
}
func TestBlockHandler_Start(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
global.LOG = zaptest.NewLogger(t).Sugar()
blockChannel := make(chan *common.BlockInfo, 1)
validTopic := make(map[string]struct{})
blockHandler := NewBlockHandler(blockChannel, validTopic, errorChannel)
blockInfo := createTestBlockInfo(1, []*common.Transaction{
createTestTransaction(common.TxStatusCode_SUCCESS, []*common.ContractEvent{
createTestContractEvent("Contract", "InvalidTopic"),
}),
}, createTestDAG(nil))
blockChannel <- blockInfo
close(blockChannel)
err := blockHandler.Start(ctx)
assert.NoError(t, err, "Expected no error starting the block handler")
select {
case event := <-blockHandler.EventChan:
assert.Equal(t, uint64(1), event.Height)
case <-time.After(1 * time.Second):
t.Error("Expected to receive block event")
}
cancel()
time.Sleep(50 * time.Millisecond)
}
......@@ -8,7 +8,6 @@ package listen
import (
"context"
"fmt"
"time"
"chainmaker.org/chainmaker/pb-go/v2/common"
......@@ -39,24 +38,25 @@ func (e *EventListener) Start(ctx context.Context) error {
//service start, subscribe block
blockChan, err := initialize.MainSdkClient.SdkClient.SubscribeBlock(ctx, e.startBlock, e.endBlock, false, false)
if err != nil {
global.LOG.Error("start SubscribeBlock err: " + err.Error() + "sleep 30s...")
global.LOG.Errorf("start SubscribeBlock err: %v, sleep 30s... ", err.Error())
//return err
}
go func() {
for {
var exit bool
if blockChan != nil {
// process subscribe result
exit = e.processBlockInfo(ctx, blockChan)
}
if exit {
global.LOG.Error("processBlockInfo exit")
return
}
global.LOG.Error("processBlockInfo exit, sleep 30s...")
time.Sleep(30 * time.Second)
//re-subscribe
blockChan, err = initialize.MainSdkClient.SdkClient.SubscribeBlock(ctx, e.startBlock, e.endBlock, false, false)
if err != nil {
global.LOG.Error("SubscribeBlock err: " + err.Error())
global.LOG.Errorf("SubscribeBlock err: %v, sleep 30s..." + err.Error())
}
}
}()
......@@ -84,7 +84,6 @@ func (e *EventListener) processBlockInfo(ctx context.Context, blockChan <-chan i
blockInfo, ok := block.(*common.BlockInfo)
if !ok {
global.LOG.Error("require block struct not is BlockInfo")
e.errorC <- fmt.Errorf("require block struct not is BlockInfo")
return false
}
......
......@@ -7,85 +7,175 @@ package listen
import (
"context"
"encoding/json"
"fmt"
"strconv"
"errors"
"os"
"testing"
"time"
"chainmaker.org/chainmaker/pb-go/v2/common"
com "chainweaver.org.cn/chainweaver/did/did-sync/common"
"chainweaver.org.cn/chainweaver/did/did-sync/config"
sdkmock "chainmaker.org/chainmaker/sdk-go/v2/mock"
"chainweaver.org.cn/chainweaver/did/did-sync/global"
"chainweaver.org.cn/chainweaver/did/did-sync/initialize"
"github.com/stretchr/testify/require"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"go.uber.org/zap/zaptest"
)
func TestListen(t *testing.T) {
global.GVA_VP = com.Viper("../../etc_test/config.yaml") // 初始化Viper
global.LOG = initialize.Zap(global.CONFIG.Zap)
func createBlockInfo(height uint64) *common.BlockInfo {
return &common.BlockInfo{
Block: &common.Block{
Header: &common.BlockHeader{
BlockHeight: height,
},
},
}
}
initialize.InitSdk(global.CONFIG.MainCmSdk, false, global.LOG)
var (
mockCtrl *gomock.Controller
mockClient *sdkmock.MockSDKInterface
)
listener := NewEventListener(int64(70120), -1, nil)
ctx := context.Background()
func TestMain(m *testing.M) {
err := listener.Start(ctx)
if err != nil {
require.Nil(t, err)
}
mockCtrl = gomock.NewController(nil) // 初始化 gomock 控制器
mockClient = sdkmock.NewMockSDKInterface(mockCtrl)
block := <-listener.BlockChan
blockInfo, err := json.Marshal(block)
if err != nil {
require.Nil(t, err)
}
fmt.Printf("BlockInfo %s\n", string(blockInfo))
initialize.MainSdkClient.SdkClient = mockClient
// 执行测试
exitVal := m.Run()
// 这里可以进行全局清理,如果有的话
mockCtrl.Finish()
// 退出,返回测试结果状态码
os.Exit(exitVal)
}
func TestUnitWithString(t *testing.T) {
conf := config.CmSdk{
ChainConfig: config.ChainConfig{
SdkPath: "./testdata/sdk_config_pk_pubnet.yml",
ChainId: initialize.MainChain,
},
func TestEventListener_Start(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
global.LOG = zaptest.NewLogger(t).Sugar()
blockChannel := make(chan interface{}, 1)
errorChannel := make(chan error)
eventListener := NewEventListener(0, 100, errorChannel)
mockClient.EXPECT().SubscribeBlock(gomock.Any(), int64(0), int64(100), false, false).
Return(blockChannel, nil).Times(1)
err := eventListener.Start(ctx)
assert.NoError(t, err, "Expected no error starting the event listener")
blockChannel <- createBlockInfo(1)
select {
case block := <-eventListener.BlockChan:
assert.Equal(t, uint64(1), block.Block.Header.BlockHeight)
case <-time.After(1 * time.Second):
t.Error("Expected to receive block information")
}
initialize.InitSdk(conf, false, nil)
sconf := config.CmSdk{
ChainConfig: config.ChainConfig{
SdkPath: "./testdata/sdk_config.yml",
ChainId: initialize.MainChain,
},
cancel()
time.Sleep(50 * time.Millisecond)
}
func TestEventListener_StartWithError(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
global.LOG = zaptest.NewLogger(t).Sugar()
errorChannel := make(chan error)
eventListener := NewEventListener(0, 100, errorChannel)
mockClient.EXPECT().SubscribeBlock(gomock.Any(), int64(0), int64(100), false, false).
Return(nil, errors.New("subscribe error")).Times(1)
err := eventListener.Start(ctx)
assert.NoError(t, err, "Expected no error starting the event listener due to internal handling")
select {
case <-errorChannel:
// Error channel should not receive any error due to internal error handling
t.Error("Did not expect to receive an error on error channel")
case <-time.After(1 * time.Second):
}
initialize.InitSdk(sconf, true, nil)
cancel()
time.Sleep(50 * time.Millisecond)
}
contractName := "did_sub"
func Test_processBlockInfo(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
blockInfo, err := initialize.MainSdkClient.SdkClient.GetBlockByHeight(uint64(70000), false)
require.NoError(t, err)
global.LOG = zaptest.NewLogger(t).Sugar()
str := strconv.FormatUint(blockInfo.Block.Header.BlockHeight, 10)
setBlockHeightKv := []*common.KeyValuePair{
{
Key: "blockHeight",
Value: []byte(str),
},
eventListener := NewEventListener(0, 100, make(chan error))
blockChannel := make(chan interface{}, 1)
go func() {
blockChannel <- createBlockInfo(1)
close(blockChannel)
}()
exit := eventListener.processBlockInfo(ctx, blockChannel)
assert.False(t, exit, "Expected false, as the block channel is closed normally")
select {
case block := <-eventListener.BlockChan:
assert.Equal(t, uint64(1), block.Block.Header.BlockHeight)
case <-time.After(1 * time.Second):
t.Error("Expected to receive block information")
}
}
setBlockHeight := "SetBlockHeight"
resp2, err := initialize.SubSdkClient.SdkClient.InvokeContract(contractName, setBlockHeight, "", setBlockHeightKv, -1, true)
require.NoError(t, err)
require.Equal(t, common.TxStatusCode_SUCCESS, resp2.Code)
func Test_processBlockInfoWithContextCancellation(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
getBlockHeight := "GetBlockHeight"
resp, err := initialize.SubSdkClient.SdkClient.QueryContract(contractName, getBlockHeight, nil, -1)
require.NoError(t, err)
require.Equal(t, common.TxStatusCode_SUCCESS, resp.Code)
global.LOG = zaptest.NewLogger(t).Sugar()
bytes := resp.ContractResult.Result
height, err := strconv.ParseUint(string(bytes), 10, 64)
eventListener := NewEventListener(0, 100, make(chan error))
expect := uint64(70000)
require.Equal(t, expect, height)
blockChannel := make(chan interface{})
go func() {
time.Sleep(100 * time.Millisecond)
cancel()
}()
exit := eventListener.processBlockInfo(ctx, blockChannel)
assert.True(t, exit, "Expected true due to context cancellation")
}
func Test_processBlockInfoWithLowerBlockHeight(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
global.LOG = zaptest.NewLogger(t).Sugar()
eventListener := NewEventListener(100, 200, make(chan error)) // startBlock 初始化为 100
blockChannel := make(chan interface{}, 1)
go func() {
blockChannel <- createBlockInfo(50) // 发送一个区块高度小于 startBlock 的区块信息
close(blockChannel)
}()
exit := eventListener.processBlockInfo(ctx, blockChannel)
assert.False(t, exit, "Expected false, as the block channel is closed normally")
select {
case <-eventListener.BlockChan:
t.Error("Did not expect to receive block information as block height is lower than startBlock")
case <-time.After(1 * time.Second):
// Expected behavior: no block info should be sent to BlockChan
}
}
......@@ -66,6 +66,7 @@ func (e *EventsCommit) loop(ctx context.Context) {
global.LOG.Debug(fmt.Sprintf("events %+v", event))
// 向子链发送同步事件
err := invokeUserContract(initialize.SubSdkClient.SdkClient, true, event)
if err != nil {
global.LOG.Error(fmt.Sprintf("commit block[%d] events to sunchain err[%s]", event.Height, err))
......@@ -86,7 +87,7 @@ func (e *EventsCommit) loop(ctx context.Context) {
}
}
func invokeUserContract(client *sdk.ChainClient, withSyncResult bool, events *com.BlockEvent) error {
func invokeUserContract(client sdk.SDKInterface, withSyncResult bool, events *com.BlockEvent) error {
contractName = global.CONFIG.SubCmSdk.ContractName
var eventList []*common.ContractEvent
for _, list := range events.Events {
......@@ -112,27 +113,31 @@ func invokeUserContract(client *sdk.ChainClient, withSyncResult bool, events *co
},
}
//todo circulation
circularInvokeContract(client, contractName, method, kvs, -1, withSyncResult)
// 循环发送合约请求
circularInvokeContract(client, contractName, method, kvs, -1, withSyncResult, 300)
return nil
}
func circularInvokeContract(client *sdk.ChainClient, contractName, method string, kvs []*common.KeyValuePair,
timeout int64, withSyncResult bool) {
func circularInvokeContract(client sdk.SDKInterface, contractName, method string, kvs []*common.KeyValuePair,
timeout int64, withSyncResult bool, delay int) {
for {
// 生成交易ID
txId := utils.GetTimestampTxId()
global.LOG.Debugf("invoke contract, [contractName:%s]/[method:%s]/[txId:%s]/[kvs:%v]",
contractName, method, txId, kvs)
// SDK 调用合约请求,若调用失败(子链未正常运行等)则等待一段时间后重试
resp, err := client.InvokeContract(contractName, method, txId, kvs, timeout, withSyncResult)
if err != nil {
global.LOG.Errorf("The Client failed to invoke the contract: %s", err)
time.Sleep(5 * time.Minute)
time.Sleep(time.Duration(delay) * time.Second)
continue
}
// 如果响应结果失败(同步合约存在错误)则等待一段时间后重试
if resp.Code != common.TxStatusCode_SUCCESS {
global.LOG.Errorf("invoke contract with [kvs:%v] failed, [code:%d]/[msg:%s]/[contractResult:%s]",
kvs, resp.Code, resp.Message, resp.ContractResult)
time.Sleep(5 * time.Minute)
time.Sleep(time.Duration(delay) * time.Second)
continue
}
......
// Copyright (C) BABEC. All rights reserved.
// Copyright (C) THL A29 Limited, a Tencent company. All rights reserved.
//
// SPDX-License-Identifier: Apache-2.0
// Package write 提交逻辑
package write
import (
"context"
sql2 "database/sql"
"errors"
"fmt"
"os"
"testing"
"time"
"chainmaker.org/chainmaker/pb-go/v2/common"
sdkmock "chainmaker.org/chainmaker/sdk-go/v2/mock"
com "chainweaver.org.cn/chainweaver/did/did-sync/common"
"chainweaver.org.cn/chainweaver/did/did-sync/db/sqlite"
"chainweaver.org.cn/chainweaver/did/did-sync/global"
"chainweaver.org.cn/chainweaver/did/did-sync/initialize"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"go.uber.org/zap/zaptest"
sql "gorm.io/driver/sqlite"
"gorm.io/gorm"
)
// createTestContractEvent 创建 ContractEvent 对象
func createTestContractEvent(contractName, topic string) *common.ContractEvent {
return &common.ContractEvent{
ContractName: contractName,
Topic: topic,
}
}
var (
mockCtrl *gomock.Controller
mockClient *sdkmock.MockSDKInterface
errorChannel = make(chan error)
failResponses = &common.TxResponse{Code: common.TxStatusCode_INTERNAL_ERROR, Message: "fail"}
successResponse = &common.TxResponse{Code: common.TxStatusCode_SUCCESS, Message: "success"}
)
// TestMain将在所有测试之前运行
func TestMain(m *testing.M) {
global.CONFIG.EventContract.Name = "Contract"
global.GVA_DB, _ = gorm.Open(sql.Open("file::memory:?cache=shared"),
&gorm.Config{SkipDefaultTransaction: true})
db, _ := global.GVA_DB.DB()
defer func(db *sql2.DB) {
err := db.Close()
if err != nil {
fmt.Println(err)
}
}(db)
err := global.GVA_DB.AutoMigrate(
sqlite.State{},
)
if err != nil {
fmt.Println(err)
}
mockCtrl = gomock.NewController(nil) // 初始化 gomock 控制器
mockClient = sdkmock.NewMockSDKInterface(mockCtrl)
initialize.SubSdkClient.SdkClient = mockClient
// 执行测试
exitVal := m.Run()
// 这里可以进行全局清理,如果有的话
mockCtrl.Finish()
// 退出,返回测试结果状态码
os.Exit(exitVal)
}
func Test_circularInvokeContract(t *testing.T) {
callIndex := 0
// Using DoAndReturn to simulate different responses based on call count
mockClient.EXPECT().
InvokeContract(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), int64(-1), true).
DoAndReturn(func(contractName, method, txId string, kvs []*common.KeyValuePair, timeout int64,
withSyncResult bool) (*common.TxResponse, error) {
defer func() { callIndex++ }()
switch callIndex {
case 0:
return nil, errors.New("InvokeContract error")
case 1:
return failResponses, nil
default:
return successResponse, nil
}
}).Times(3)
global.LOG = zaptest.NewLogger(t).Sugar()
start := time.Now()
circularInvokeContract(mockClient, contractName, method, nil, -1, true, 5)
end := time.Now()
duration := end.Sub(start)
staticSleepDuration := 10 * time.Second
assert.GreaterOrEqual(t, duration, staticSleepDuration,
"Expected duration should be greater or equal to the total sleep duration")
}
func Test_Start(t *testing.T) {
mockClient.EXPECT().InvokeContract(contractName, method, gomock.Any(), gomock.Any(),
int64(-1), true).Return(successResponse, nil).AnyTimes()
global.LOG = zaptest.NewLogger(t).Sugar()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
eventChan := make(chan *com.BlockEvent, 1)
eventsCommit := NewBlockHandler(eventChan, errorChannel)
event := &com.BlockEvent{
Height: 1,
Events: [][]*common.ContractEvent{{createTestContractEvent("Contract", "Topic")}},
}
eventChan <- event
err := eventsCommit.Start(ctx)
assert.NoError(t, err, "Expected no error starting the block handler")
//go eventsCommit.loop(ctx)
select {
case err := <-errorChannel:
assert.Error(t, err, "Expected error when processing block event")
case <-ctx.Done():
t.Error("Context was canceled unexpectedly")
case <-time.After(1 * time.Second):
t.Log("Loop executed without errors")
}
cancel()
time.Sleep(50 * time.Millisecond)
}
......@@ -36,9 +36,9 @@ func GetState(chainType string) (*State, error) {
return &state, err
}
// UpdateChain 更新
// UpdateChain 更新表连接
func (s *State) UpdateChain(conn *gorm.DB) error {
err := conn.Model(s).Updates(s).Error
err := conn.Model(s).Where("chain_type", s.ChainType).Updates(s).Error
return err
}
......@@ -47,7 +47,7 @@ func (s *State) UpdateStateHeight(chainType string, height uint64) error {
return global.GVA_DB.Model(s).Where("chain_type = ?", chainType).Update("sync_height", height).Error
}
// DropState 删除数据
// DropState 删除数据
func DropState(conn *gorm.DB) error {
return conn.Exec("DROP TABLE state").Error
}
// Copyright (C) BABEC. All rights reserved.
// Copyright (C) THL A29 Limited, a Tencent company. All rights reserved.
//
// SPDX-License-Identifier: Apache-2.0
// Package sqlite 数据库
package sqlite
import (
"testing"
"chainweaver.org.cn/chainweaver/did/did-sync/global"
"github.com/stretchr/testify/assert"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
func TestSQLiteFunctions(t *testing.T) {
global.GVA_DB, _ = gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{SkipDefaultTransaction: true})
// 创建测试所需的表
err := global.GVA_DB.AutoMigrate(&State{})
assert.NoError(t, err)
// 测试插入状态
state := &State{
ChainType: "testChain",
SyncHeight: 100,
}
insertedState, err := state.InsertStatus()
assert.NoError(t, err, "InsertStatus should not return an error")
var retrievedState *State
err = global.GVA_DB.First(&retrievedState, "chain_type = ?", "testChain").Error
assert.NoError(t, err)
assert.Equal(t, insertedState.ChainType, retrievedState.ChainType)
assert.Equal(t, insertedState.SyncHeight, retrievedState.SyncHeight)
// 测试获取状态
retrievedState, err = GetState("testChain")
assert.NoError(t, err, "GetState should not return an error")
assert.Equal(t, state.ChainType, retrievedState.ChainType)
assert.Equal(t, state.SyncHeight, retrievedState.SyncHeight)
// 测试更新链状态
state.SyncHeight = 200
err = state.UpdateChain(global.GVA_DB)
assert.NoError(t, err, "UpdateChain should not return an error")
err = global.GVA_DB.First(&retrievedState, "chain_type = ?", "testChain").Error
assert.NoError(t, err)
assert.Equal(t, int64(200), retrievedState.SyncHeight)
// 测试更新状态高度
err = state.UpdateStateHeight("testChain", 300)
assert.NoError(t, err, "UpdateStateHeight should not return an error")
err = global.GVA_DB.First(&retrievedState, "chain_type = ?", "testChain").Error
assert.NoError(t, err)
assert.Equal(t, int64(300), retrievedState.SyncHeight)
// 测试删除表
err = DropState(global.GVA_DB)
assert.NoError(t, err, "DropState should not return an error")
// 验证表是否删除
err = global.GVA_DB.First(&state, "chain_type = ?", "testChain").Error
assert.Error(t, err, "Querying a dropped table should return an error")
}
......@@ -4,10 +4,10 @@ go 1.22
require (
chainmaker.org/chainmaker/pb-go/v2 v2.3.5
chainmaker.org/chainmaker/sdk-go/v2 v2.3.6-0.20240711031433-57b7514c63ba
chainmaker.org/chainmaker/sdk-go/v2 v2.3.6
chainweaver.org.cn/chainweaver/servicecommon v1.1.1
github.com/fsnotify/fsnotify v1.5.1
github.com/go-redis/redis/v8 v8.11.4
github.com/golang/mock v1.6.0
github.com/spf13/viper v1.9.0
github.com/stretchr/testify v1.9.0
go.uber.org/zap v1.27.0
......@@ -16,6 +16,8 @@ require (
gorm.io/gorm v1.25.7-0.20240204074919-46816ad31dde
)
replace chainmaker.org/chainmaker/sdk-go/v2 => chainweaver.org.cn/chainweaver/sdk-go/v2 v2.3.6-0.20240730063620-2d7127f68f97
require (
chainmaker.org/chainmaker/common/v2 v2.3.4 // indirect
chainmaker.org/chainmaker/protocol/v2 v2.3.5 // indirect
......@@ -64,9 +66,7 @@ require (
require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/s2a-go v0.1.8 // indirect
github.com/googleapis/gax-go/v2 v2.13.0 // indirect
......
......@@ -4,10 +4,10 @@ chainmaker.org/chainmaker/pb-go/v2 v2.3.5 h1:2PE8XJNFyBw++qUD7dIv8mgLIlHtoybz86V
chainmaker.org/chainmaker/pb-go/v2 v2.3.5/go.mod h1:GXGRIYS+d6bcgmmqKrW7nNBh3mIHE1EwTLv96811OtE=
chainmaker.org/chainmaker/protocol/v2 v2.3.5 h1:OUZp596mr6uRDS0exO6D/M1WUwNdkgrrBxCKmq5NMuI=
chainmaker.org/chainmaker/protocol/v2 v2.3.5/go.mod h1:UDPjfqLH89QY8FbWxfEqNcWS2W5pk/z0pU7zo1FAzyI=
chainmaker.org/chainmaker/sdk-go/v2 v2.3.6-0.20240711031433-57b7514c63ba h1:jp+LIM03iWKsz7tcreBGOJnbHaFhVXHqXo+31bJbjSg=
chainmaker.org/chainmaker/sdk-go/v2 v2.3.6-0.20240711031433-57b7514c63ba/go.mod h1:Bzdi+8xz4qxLr5RT9AZmFJ/NzpiRVeJHsEGKaHSDelg=
chainmaker.org/chainmaker/utils/v2 v2.3.5 h1:m8jZPsuQh8VhZq3R82SvCkWVzm8Dok3/7L7Bz2B/OfI=
chainmaker.org/chainmaker/utils/v2 v2.3.5/go.mod h1:LlCRtHxbWYDJGFpp7ImFfQuptAl65a8Dtt/SA3OZbE8=
chainweaver.org.cn/chainweaver/sdk-go/v2 v2.3.6-0.20240730063620-2d7127f68f97 h1:tCjUAmZiS0QzlLOigjx056nLqBcna6evWkGny5kYSHU=
chainweaver.org.cn/chainweaver/sdk-go/v2 v2.3.6-0.20240730063620-2d7127f68f97/go.mod h1:Bzdi+8xz4qxLr5RT9AZmFJ/NzpiRVeJHsEGKaHSDelg=
chainweaver.org.cn/chainweaver/servicecommon v1.1.1 h1:kLITrrP+6vpgvteH+0Cl11Wgve6E6Qioasj+QgCH7DQ=
chainweaver.org.cn/chainweaver/servicecommon v1.1.1/go.mod h1:N3Qdug4x+OabVA3B34AZYfv0vyOkKz78evpbSKKWZhs=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
......@@ -153,7 +153,6 @@ github.com/cep21/xdgbasedir v0.0.0-20170329171747-21470bfc93b9/go.mod h1:6R3C29d
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cheggaaa/pb/v3 v3.0.1/go.mod h1:SqqeMF/pMOIu3xgGoxtPYhMNQP258xE4x/XRTYua+KU=
......@@ -226,8 +225,6 @@ github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczC
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165 h1:BS21ZUJ/B5X2UVUbczfmdWH7GapPWAhxcMsDnjJTU1E=
github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
......@@ -326,8 +323,6 @@ github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTM
github.com/go-playground/overalls v0.0.0-20180201144345-22ec1a223b7c/go.mod h1:UqxAgEOt89sCiXlrc/ycnx00LVvUO/eS8tMUkWX4R7w=
github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-redis/redis/v8 v8.11.4 h1:kHoYkfZP6+pe04aFTnhDH6GDROa5yJdHJVNxV3F46Tg=
github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
......@@ -335,7 +330,6 @@ github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/goccy/go-graphviz v0.0.5/go.mod h1:wXVsXxmyMQU6TN3zGRttjNn3h+iCAS7xQFC6TlNvLhk=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/gateway v1.1.0/go.mod h1:S7rR8FRQyG3QFESeSv4l2WnsyzlCLG0CzBbUUo/mbic=
......@@ -721,8 +715,6 @@ github.com/ngaut/sync2 v0.0.0-20141008032647-7a24ed77b2ef/go.mod h1:7WjlapSfwQyo
github.com/nicksnyder/go-i18n v1.10.0/go.mod h1:HrK7VCrbOvQoUAQ7Vpy7i87N7JZZZ7R2xBGjv0j365Q=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
......@@ -733,16 +725,12 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c=
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
github.com/opentracing/basictracer-go v1.0.0 h1:YyUAhaEfjoWXclZVJ9sGoNct7j4TVk7lZWlQw5UXuoo=
......@@ -1237,7 +1225,6 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
......@@ -1339,7 +1326,6 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
......@@ -1444,7 +1430,6 @@ golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20201125231158-b5590deeca9b/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
......@@ -1643,7 +1628,6 @@ gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
......
......@@ -13,6 +13,7 @@ import (
"chainweaver.org.cn/chainweaver/did/did-sync/global"
"go.uber.org/zap"
sql "gorm.io/driver/sqlite"
"gorm.io/gorm"
)
......@@ -27,6 +28,20 @@ func Gorm() *gorm.DB {
}
}
// StartSqliteConnect 创建 sql 链接
func StartSqliteConnect(path string) *gorm.DB {
if path == "" {
path = "./sqlite.db"
}
db, err := gorm.Open(sql.Open(path), &gorm.Config{})
if err != nil {
global.LOG.Fatal("Sqlite db start err : " + err.Error())
}
return db
}
// RegisterTables 注册数据库表专用
func RegisterTables(db *gorm.DB) {
err := db.AutoMigrate(
......
// Copyright (C) BABEC. All rights reserved.
// Copyright (C) THL A29 Limited, a Tencent company. All rights reserved.
//
// SPDX-License-Identifier: Apache-2.0
package initialize
import (
"context"
"fmt"
"chainweaver.org.cn/chainweaver/did/did-sync/config"
"github.com/go-redis/redis/v8"
)
var (
// RedisClient redis
RedisClient = &redis.Client{}
)
// InitRedis 初始化redis
func InitRedis(cfg *config.RedisConfig) *redis.Client {
client := redis.NewClient(&redis.Options{
Addr: cfg.Addr,
Password: cfg.Password,
DB: cfg.DB,
Username: cfg.UserName,
})
_, err := client.Ping(context.Background()).Result()
if err != nil {
panic(fmt.Sprintf("InitRedis failed %s ", err.Error()))
}
RedisClient = client
return client
}
......@@ -21,7 +21,7 @@ var (
// ClientSdk sdk client
type ClientSdk struct {
SdkClient *sdk.ChainClient
SdkClient sdk.SDKInterface
ChainConfig config.ChainConfig
Admin []config.Admin
}
......@@ -36,7 +36,6 @@ const (
func InitSdk(sdkConf config.CmSdk, sub bool, logger *zap.SugaredLogger) *sdk.ChainClient {
var (
sdkConfigPath string
admin []config.Admin
client *sdk.ChainClient
err error
......@@ -46,9 +45,9 @@ func InitSdk(sdkConf config.CmSdk, sub bool, logger *zap.SugaredLogger) *sdk.Cha
clientSDk = &ClientSdk{}
sdkConfigPath = sdkConf.ChainConfig.SdkPath
admin = sdkConf.ChainConfig.Admins
if logger != nil {
// 区分主子链日志
if sub {
logger = logger.Named("[SubChain-SDK]")
} else {
......@@ -68,9 +67,10 @@ func InitSdk(sdkConf config.CmSdk, sub bool, logger *zap.SugaredLogger) *sdk.Cha
panic(err)
}
clientSDk.Admin = admin
clientSDk.Admin = sdkConf.ChainConfig.Admins
clientSDk.SdkClient = client
// 全局参数
if sub {
SubSdkClient = clientSDk
} else {
......
// Copyright (C) BABEC. All rights reserved.
// Copyright (C) THL A29 Limited, a Tencent company. All rights reserved.
//
// SPDX-License-Identifier: Apache-2.0
package initialize
import (
"context"
"fmt"
"testing"
"chainmaker.org/chainmaker/pb-go/v2/common"
"chainweaver.org.cn/chainweaver/did/did-sync/config"
"github.com/stretchr/testify/require"
)
func TestSdk(t *testing.T) {
sconf := config.CmSdk{
ChainConfig: config.ChainConfig{
SdkPath: "../test/sdk_config_pk_pubnet.yml",
ChainId: MainChain,
},
}
client := InitSdk(sconf, false, nil)
conf, err := client.GetChainConfig()
require.Nil(t, err)
fmt.Printf("chainConfig %+v\n", conf)
chainInfo, err := client.GetChainInfo()
require.Nil(t, err)
fmt.Printf("chainInfo %+v\n", chainInfo)
list, err := client.GetContractList()
require.Nil(t, err)
for _, name := range list {
fmt.Printf("contractList %+v\n", name)
}
}
func TestSendEvidenceTx(t *testing.T) {
sconf := config.CmSdk{
ChainConfig: config.ChainConfig{
SdkPath: "../test/sdk_config_pk_pubnet.yml",
ChainId: MainChain,
},
}
client := InitSdk(sconf, false, nil)
/* config, err := client.GetChainConfig()
require.Nil(t, err)*/
kvs := []*common.KeyValuePair{
{
Key: "id",
Value: []byte("wx-org-001"),
},
{
Key: "hash",
Value: []byte("520e086df734d00a40301a10934d127n"),
},
{
Key: "metadata",
Value: []byte(`"{"
hashType ":"
file ","
hashAlgorithm ":"
md5 ","
username ":"
taifu ","
timestamp ":"
1672048892 ","
proveTimestamp ":"
"}"`),
},
}
payload := client.CreatePayload("", common.TxType_INVOKE_CONTRACT, "evidence", "Evidence", kvs, 0, &common.Limit{
GasLimit: 90000000,
})
req, err := client.GenerateTxRequest(payload, nil)
require.Nil(t, err)
res, err := client.SendTxRequest(req, 0, true)
require.Nil(t, err)
fmt.Printf("Result is %+v", res)
}
func TestEvents(t *testing.T) {
sconf := config.CmSdk{
ChainConfig: config.ChainConfig{
SdkPath: "../test/sdk_config_pk_pubnet.yml",
ChainId: MainChain,
},
}
client := InitSdk(sconf, false, nil)
ctx := context.Background()
eventChan, err := client.SubscribeContractEvent(ctx, int64(47000), int64(-1), "DID1", "")
require.Nil(t, err)
event, ok := <-eventChan
if !ok {
fmt.Println("chan is close!")
return
}
contractEventInfo, ok := event.(*common.ContractEventInfo)
if !ok {
fmt.Println("the type pf event isn't *common.ContractEventInfo")
return
}
fmt.Printf("contractEventInfo: %+v", contractEventInfo)
}
// Copyright (C) BABEC. All rights reserved.
// Copyright (C) THL A29 Limited, a Tencent company. All rights reserved.
//
// SPDX-License-Identifier: Apache-2.0
/**
* @Author: p_starxxliu
* @Date: 2021/4/17 2:05 下午
*/
package initialize
import (
"log"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
var (
sqlDB = &gorm.DB{}
)
// StartSqliteConnect 创建 sql 链接
func StartSqliteConnect(path string) *gorm.DB {
if path == "" {
path = "./sqlite.db"
}
db, err := gorm.Open(sqlite.Open(path), &gorm.Config{})
if err != nil {
log.Fatal("Sqlite db start err : " + err.Error())
}
sqlDB = db
return db
}
// GetDB 获取DB
func GetDB() *gorm.DB {
return sqlDB
}
// Close 关闭DB
func Close() {
sqlDB, err := sqlDB.DB()
if err != nil {
panic("close mysql db err: " + err.Error())
}
sqlDB.Close()
}
......@@ -30,6 +30,7 @@ func Zap(config config.Zap) *zap.SugaredLogger {
encoderConfig := getEncoderConfig()
// 日志输出形式
var encoder zapcore.Encoder
if config.Format == "json" {
encoder = zapcore.NewJSONEncoder(encoderConfig)
......@@ -37,6 +38,7 @@ func Zap(config config.Zap) *zap.SugaredLogger {
encoder = zapcore.NewConsoleEncoder(encoderConfig)
}
// 日志级别
var level zapcore.Level
switch config.Level {
case "debug":
......@@ -52,6 +54,7 @@ func Zap(config config.Zap) *zap.SugaredLogger {
}
logger := zap.New(zapcore.NewCore(encoder, syncer, level)).Named(config.Prefix).Sugar()
// 确保日志输出完毕
defer func(logger *zap.SugaredLogger) {
_ = logger.Sync()
}(logger)
......
// Copyright (C) BABEC. All rights reserved.
// Copyright (C) THL A29 Limited, a Tencent company. All rights reserved.
//
// SPDX-License-Identifier: Apache-2.0
package initialize
import (
"os"
"testing"
"chainweaver.org.cn/chainweaver/did/did-sync/config"
"github.com/stretchr/testify/assert"
)
// 创建测试日志配置
func createTestConfig(path, level, format string, logInConsole, showLine bool, prefix string) config.Zap {
return config.Zap{
Path: path,
Level: level,
Format: format,
LogInConsole: logInConsole,
ShowLine: showLine,
Prefix: prefix,
}
}
func TestZapLogger(t *testing.T) {
tests := []struct {
name string
config config.Zap
expectedErr error
}{
{
name: "ConsoleLogger",
config: createTestConfig("test_console.log", "info", "console", true, true, "test"),
expectedErr: nil,
},
{
name: "JsonLogger",
config: createTestConfig("test_json.log", "debug", "json", false, false, "test"),
expectedErr: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.expectedErr != nil {
defer func() {
if r := recover(); r == nil {
t.Errorf("Expected error but got none")
}
}()
}
logger := Zap(tt.config)
assert.NotNil(t, logger)
logger.Infof("Test message for %s", tt.name)
// 验证文件输出(检查日志文件是否创建)
if tt.config.Path != "" {
_, err := os.Stat(tt.config.Path)
assert.NoError(t, err, "Expected log file to exist")
}
})
}
}
......@@ -30,8 +30,6 @@ func main() {
initialize.RegisterTables(global.GVA_DB) // 初始化表
// 程序结束前关闭数据库链接
db, _ := global.GVA_DB.DB()
// 初始化db
common.InitDbStruct(global.GVA_DB)
defer db.Close()
}
......@@ -45,8 +43,6 @@ func main() {
errorC := make(chan error, 1)
ctx, cancel := context.WithCancel(context.Background())
// TODO loop listening other sync service
sync, err := core.NewSyncHandle(ctx, errorC)
if err != nil {
global.LOG.Error(fmt.Sprintf("sync service encounters error: %s ", err.Error()))
......@@ -55,6 +51,7 @@ func main() {
err = sync.StartSync()
if err != nil {
global.LOG.Error(fmt.Sprintf("sync service encounters error: %s ", err.Error()))
return
}
// handle exit signal in separate go routines
......
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