Commit 92b0e754 authored by vipwzw's avatar vipwzw

fix build

parent 4d5ff203
...@@ -113,7 +113,7 @@ func makeCommitReceipt(addr string, commit *pt.ParacrossCommitAction, prev, curr ...@@ -113,7 +113,7 @@ func makeCommitReceipt(addr string, commit *pt.ParacrossCommitAction, prev, curr
return &types.Receipt{ return &types.Receipt{
Ty: types.ExecOk, Ty: types.ExecOk,
KV: []*types.KeyValue{ KV: []*types.KeyValue{
{key, types.Encode(current)}, {Key: key, Value: types.Encode(current)},
}, },
Logs: []*types.ReceiptLog{ Logs: []*types.ReceiptLog{
{ {
...@@ -163,7 +163,7 @@ func makeDoneReceipt(addr string, commit *pt.ParacrossCommitAction, current *pt. ...@@ -163,7 +163,7 @@ func makeDoneReceipt(addr string, commit *pt.ParacrossCommitAction, current *pt.
return &types.Receipt{ return &types.Receipt{
Ty: types.ExecOk, Ty: types.ExecOk,
KV: []*types.KeyValue{ KV: []*types.KeyValue{
{key, types.Encode(stat)}, {Key: key, Value: types.Encode(stat)},
}, },
Logs: []*types.ReceiptLog{ Logs: []*types.ReceiptLog{
{ {
......
...@@ -92,7 +92,7 @@ func (c *Jrpc) ShowPrivacyAccountInfo(in *pty.ReqPPrivacyAccount, result *json.R ...@@ -92,7 +92,7 @@ func (c *Jrpc) ShowPrivacyAccountInfo(in *pty.ReqPPrivacyAccount, result *json.R
if err != nil { if err != nil {
return err return err
} }
*result, err = types.PBToJson(reply) *result, err = types.PBToJSON(reply)
return err return err
} }
...@@ -108,7 +108,7 @@ func (c *Jrpc) ShowPrivacyAccountSpend(in *pty.ReqPrivBal4AddrToken, result *jso ...@@ -108,7 +108,7 @@ func (c *Jrpc) ShowPrivacyAccountSpend(in *pty.ReqPrivBal4AddrToken, result *jso
log.Info("ShowPrivacyAccountSpend", "return err info", err) log.Info("ShowPrivacyAccountSpend", "return err info", err)
return err return err
} }
*result, err = types.PBToJson(reply) *result, err = types.PBToJSON(reply)
return err return err
} }
...@@ -118,7 +118,7 @@ func (c *Jrpc) ShowPrivacykey(in *types.ReqString, result *json.RawMessage) erro ...@@ -118,7 +118,7 @@ func (c *Jrpc) ShowPrivacykey(in *types.ReqString, result *json.RawMessage) erro
if err != nil { if err != nil {
return err return err
} }
*result, err = types.PBToJson(reply) *result, err = types.PBToJSON(reply)
return err return err
} }
...@@ -192,7 +192,7 @@ func (c *Jrpc) RescanUtxos(in *pty.ReqRescanUtxos, result *json.RawMessage) erro ...@@ -192,7 +192,7 @@ func (c *Jrpc) RescanUtxos(in *pty.ReqRescanUtxos, result *json.RawMessage) erro
if err != nil { if err != nil {
return err return err
} }
*result, err = types.PBToJson(reply) *result, err = types.PBToJSON(reply)
return err return err
} }
...@@ -202,7 +202,7 @@ func (c *Jrpc) EnablePrivacy(in *pty.ReqEnablePrivacy, result *json.RawMessage) ...@@ -202,7 +202,7 @@ func (c *Jrpc) EnablePrivacy(in *pty.ReqEnablePrivacy, result *json.RawMessage)
if err != nil { if err != nil {
return err return err
} }
*result, err = types.PBToJson(reply) *result, err = types.PBToJSON(reply)
return err return err
} }
......
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package types
/*
func buildPrivacyInputResult(l *rpctypes.ReceiptLogResult) interface{} {
data, _ := common.FromHex(l.RawLog)
srcInput := &pty.PrivacyInput{}
dstInput := &PrivacyInput{}
if proto.Unmarshal(data, srcInput) != nil {
return dstInput
}
for _, srcKeyInput := range srcInput.Keyinput {
var dstUtxoGlobalIndex []*UTXOGlobalIndex
for _, srcUTXOGlobalIndex := range srcKeyInput.UtxoGlobalIndex {
dstUtxoGlobalIndex = append(dstUtxoGlobalIndex, &UTXOGlobalIndex{
Outindex: srcUTXOGlobalIndex.GetOutindex(),
Txhash: common.ToHex(srcUTXOGlobalIndex.GetTxhash()),
})
}
dstKeyInput := &KeyInput{
Amount: strconv.FormatFloat(float64(srcKeyInput.GetAmount())/float64(types.Coin), 'f', 4, 64),
UtxoGlobalIndex: dstUtxoGlobalIndex,
KeyImage: common.ToHex(srcKeyInput.GetKeyImage()),
}
dstInput.Keyinput = append(dstInput.Keyinput, dstKeyInput)
}
return dstInput
}
func buildPrivacyOutputResult(l *rpctypes.ReceiptLogResult) interface{} {
data, _ := common.FromHex(l.RawLog)
srcOutput := &pty.ReceiptPrivacyOutput{}
dstOutput := &ReceiptPrivacyOutput{}
if proto.Unmarshal(data, srcOutput) != nil {
return dstOutput
}
dstOutput.Token = srcOutput.Token
for _, srcKeyoutput := range srcOutput.Keyoutput {
dstKeyoutput := &KeyOutput{
Amount: strconv.FormatFloat(float64(srcKeyoutput.GetAmount())/float64(types.Coin), 'f', 4, 64),
Onetimepubkey: common.ToHex(srcKeyoutput.Onetimepubkey),
}
dstOutput.Keyoutput = append(dstOutput.Keyoutput, dstKeyoutput)
}
return dstOutput
}
func decodePrivInput(input *pty.PrivacyInput) *PrivacyInput {
inputResult := &PrivacyInput{}
for _, value := range input.Keyinput {
amt := float64(value.Amount) / float64(types.Coin)
amtResult := strconv.FormatFloat(amt, 'f', 4, 64)
var ugis []*UTXOGlobalIndex
for _, u := range value.UtxoGlobalIndex {
ugis = append(ugis, &UTXOGlobalIndex{Outindex: u.Outindex, Txhash: common.ToHex(u.Txhash)})
}
kin := &KeyInput{
Amount: amtResult,
KeyImage: common.ToHex(value.KeyImage),
UtxoGlobalIndex: ugis,
}
inputResult.Keyinput = append(inputResult.Keyinput, kin)
}
return inputResult
}
func decodePrivOutput(output *pty.PrivacyOutput) *PrivacyOutput {
outputResult := &PrivacyOutput{RpubKeytx: common.ToHex(output.RpubKeytx)}
for _, value := range output.Keyoutput {
amt := float64(value.Amount) / float64(types.Coin)
amtResult := strconv.FormatFloat(amt, 'f', 4, 64)
kout := &KeyOutput{
Amount: amtResult,
Onetimepubkey: common.ToHex(value.Onetimepubkey),
}
outputResult.Keyoutput = append(outputResult.Keyoutput, kout)
}
return outputResult
}
*/
...@@ -177,7 +177,7 @@ func (policy *privacyPolicy) createUTXOsByPub2Priv(priv crypto.PrivKey, reqCreat ...@@ -177,7 +177,7 @@ func (policy *privacyPolicy) createUTXOsByPub2Priv(priv crypto.PrivKey, reqCreat
To: address.ExecAddress(privacytypes.PrivacyX), To: address.ExecAddress(privacytypes.PrivacyX),
} }
txSize := types.Size(tx) + types.SignatureSize txSize := types.Size(tx) + types.SignatureSize
realFee := int64((txSize+1023)>>types.Size_1K_shiftlen) * types.GInt("MinFee") realFee := int64((txSize+1023)>>types.Size1Kshiftlen) * types.GInt("MinFee")
tx.Fee = realFee tx.Fee = realFee
tx.Sign(int32(operater.GetSignType()), priv) tx.Sign(int32(operater.GetSignType()), priv)
...@@ -610,7 +610,7 @@ func (policy *privacyPolicy) createPublic2PrivacyTx(req *types.ReqCreateTransact ...@@ -610,7 +610,7 @@ func (policy *privacyPolicy) createPublic2PrivacyTx(req *types.ReqCreateTransact
} }
txSize := types.Size(tx) + types.SignatureSize txSize := types.Size(tx) + types.SignatureSize
realFee := int64((txSize+1023)>>types.Size_1K_shiftlen) * types.GInt("MinFee") realFee := int64((txSize+1023)>>types.Size1Kshiftlen) * types.GInt("MinFee")
tx.Fee = realFee tx.Fee = realFee
return tx, nil return tx, nil
} }
...@@ -1024,7 +1024,7 @@ func (policy *privacyPolicy) transPub2PriV2(priv crypto.PrivKey, reqPub2Pri *pri ...@@ -1024,7 +1024,7 @@ func (policy *privacyPolicy) transPub2PriV2(priv crypto.PrivKey, reqPub2Pri *pri
} }
tx.SetExpire(time.Duration(reqPub2Pri.GetExpire())) tx.SetExpire(time.Duration(reqPub2Pri.GetExpire()))
txSize := types.Size(tx) + types.SignatureSize txSize := types.Size(tx) + types.SignatureSize
realFee := int64((txSize+1023)>>types.Size_1K_shiftlen) * types.GInt("MinFee") realFee := int64((txSize+1023)>>types.Size1Kshiftlen) * types.GInt("MinFee")
tx.Fee = realFee tx.Fee = realFee
tx.Sign(int32(operater.GetSignType()), priv) tx.Sign(int32(operater.GetSignType()), priv)
......
# Changelog
All notable changes to this project will be documented in this file.
## [Unreleased]
## [6.0.1]
### Changed
- Update configuration files from p2p/verMix to p2p/verMin from[@libangzhu](https://github.com/libangzhu).
- Update p2p version Logic(if you do not fill in the range of p2p version,then verMin=version,verMax=verMin+1) from[@libangzhu](https://github.com/libangzhu).
package blockchain
import (
"bytes"
"compress/gzip"
"io/ioutil"
"net/http"
"sync"
"time"
"github.com/33cn/chain33/types"
)
type pushNotify struct {
cb chan *types.BlockSeqCB
seq chan int64
}
//push seq data to out
type pushseq struct {
store *BlockStore
cmds map[string]pushNotify
mu sync.Mutex
client *http.Client
}
func newpushseq(store *BlockStore) *pushseq {
cmds := make(map[string]pushNotify)
return &pushseq{store: store, cmds: cmds, client: &http.Client{}}
}
//初始化: 从数据库读出seq的数目
func (p *pushseq) init() {
cbs, err := p.store.listSeqCB()
if err != nil {
chainlog.Error("listSeqCB", "err", err)
return
}
for _, cb := range cbs {
p.addTask(cb)
}
}
func (p *pushseq) updateLastSeq() {
last, err := p.store.LoadBlockLastSequence()
if err != nil {
chainlog.Error("listSeqCB", "err", err)
return
}
p.updateSeq(last)
}
//每个name 有一个task
func (p *pushseq) addTask(cb *types.BlockSeqCB) {
p.mu.Lock()
defer p.mu.Unlock()
if notify, ok := p.cmds[cb.Name]; ok {
notify.cb <- cb
if cb.URL == "" {
delete(p.cmds, cb.Name)
}
return
}
p.cmds[cb.Name] = pushNotify{
cb: make(chan *types.BlockSeqCB, 10),
seq: make(chan int64, 10),
}
p.cmds[cb.Name].cb <- cb
p.runTask(p.cmds[cb.Name])
//更新最新的seq
p.updateLastSeq()
}
func (p *pushseq) updateSeq(seq int64) {
p.mu.Lock()
defer p.mu.Unlock()
for _, notify := range p.cmds {
notify.seq <- seq
}
}
func (p *pushseq) trigeRun(run chan struct{}, sleep time.Duration) {
go func() {
if sleep > 0 {
time.Sleep(sleep)
}
select {
case run <- struct{}{}:
default:
}
}()
}
func (p *pushseq) runTask(input pushNotify) {
go func(in pushNotify) {
var lastseq int64 = -1
var maxseq int64 = -1
var cb *types.BlockSeqCB
var run = make(chan struct{}, 10)
for {
select {
case cb = <-in.cb:
if cb.URL == "" {
return
}
p.trigeRun(run, 0)
case maxseq = <-in.seq:
p.trigeRun(run, 0)
case <-run:
if cb == nil {
p.trigeRun(run, time.Second)
continue
}
if lastseq == -1 {
lastseq = p.store.getSeqCBLastNum([]byte(cb.Name))
}
if lastseq >= maxseq {
p.trigeRun(run, 100*time.Millisecond)
continue
}
data, err := p.getDataBySeq(lastseq + 1)
if err != nil {
chainlog.Error("getDataBySeq", "err", err)
p.trigeRun(run, 1000*time.Millisecond)
continue
}
err = p.postData(cb, data)
if err != nil {
chainlog.Error("postdata", "err", err)
//sleep 10s
p.trigeRun(run, 10000*time.Millisecond)
continue
}
//update seqid
lastseq = lastseq + 1
p.trigeRun(run, 0)
}
}
}(input)
}
func (p *pushseq) postData(cb *types.BlockSeqCB, data *types.BlockSeq) (err error) {
var postdata []byte
if cb.Encode == "json" {
postdata, err = types.PBToJSON(data)
if err != nil {
return err
}
} else {
postdata = types.Encode(data)
}
//post data in body
var buf bytes.Buffer
g := gzip.NewWriter(&buf)
if _, err = g.Write(postdata); err != nil {
return err
}
if err = g.Close(); err != nil {
return err
}
req, err := http.NewRequest("POST", cb.URL, &buf)
if err != nil {
return err
}
req.Header.Set("Content-Type", "text/plain")
req.Header.Set("Content-Encoding", "gzip")
resp, err := p.client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
if string(body) != "ok" && string(body) != "OK" {
return types.ErrPushSeqPostData
}
p.store.setSeqCBLastNum([]byte(cb.Name), data.Num)
return nil
}
func (p *pushseq) getDataBySeq(seq int64) (*types.BlockSeq, error) {
seqdata, err := p.store.GetBlockSequence(seq)
if err != nil {
return nil, err
}
detail, err := p.store.LoadBlockBySequence(seq)
if err != nil {
return nil, err
}
return &types.BlockSeq{Num: seq, Seq: seqdata, Detail: detail}, nil
}
#!/usr/bin/env bash
percreate="$(../chain33-cli token precreate -s CNYY -n "CNY Coins" -i "" -p 0.000001 -t 1000000000 -a 1MY4pMgjpS2vWiaSDZasRhN47pcwEire32 -f 0.001)"
finish="$(../chain33-cli token finish -f 0.001 -a 1MY4pMgjpS2vWiaSDZasRhN47pcwEire32 -s CNYY)"
echo "cli wallet sign -d $percreate -a 1JmFaA6unrCFYEWPGRi7uuXY1KthTJxJEP -e 1h > d:/a.txt"
echo "cli wallet sign -d $finish -a 1JmFaA6unrCFYEWPGRi7uuXY1KthTJxJEP -e 1h >> d:/a.txt"
/*
* Copyright Fuzamei Corp. 2018 All Rights Reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
package strategy
//const
const (
// 創建main.go的文件模板
CPFT_MAIN_GO = `package main
import (
_ "github.com/33cn/chain33/system"
_ "${PROJECTPATH}/plugin"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/util/cli"
)
func main() {
types.S("cfg.${PROJECTNAME}", ${PROJECTNAME})
cli.RunChain33("${PROJECTNAME}")
}
`
// 生成的配置文件模板 xxx.toml
CPFT_CFG_TOML = `
Title="${PROJECTNAME}"
FixTime=false
[log]
# 日志级别,支持debug(dbug)/info/warn/error(eror)/crit
loglevel = "debug"
logConsoleLevel = "info"
# 日志文件名,可带目录,所有生成的日志文件都放到此目录下
logFile = "logs/${PROJECTNAME}.log"
# 单个日志文件的最大值(单位:兆)
maxFileSize = 300
# 最多保存的历史日志文件个数
maxBackups = 100
# 最多保存的历史日志消息(单位:天)
maxAge = 28
# 日志文件名是否使用本地事件(否则使用UTC时间)
localTime = true
# 历史日志文件是否压缩(压缩格式为gz)
compress = true
# 是否打印调用源文件和行号
callerFile = false
# 是否打印调用方法
callerFunction = false
[blockchain]
dbPath="datadir"
dbCache=64
batchsync=false
isRecordBlockSequence=false
enableTxQuickIndex=false
[p2p]
seeds=[]
isSeed=false
innerSeedEnable=true
useGithub=true
innerBounds=300
dbPath="datadir/addrbook"
dbCache=4
grpcLogFile="grpc33.log"
[rpc]
jrpcBindAddr="localhost:8801"
grpcBindAddr="localhost:8802"
whitelist=["127.0.0.1"]
jrpcFuncWhitelist=["*"]
grpcFuncWhitelist=["*"]
[mempool]
maxTxNumPerAccount=100
[store]
dbPath="datadir/mavltree"
dbCache=128
enableMavlPrefix=false
enableMVCC=false
enableMavlPrune=false
pruneHeight=10000
[wallet]
dbPath="wallet"
dbCache=16
[wallet.sub.ticket]
minerdisable=false
minerwhitelist=["*"]
[exec]
enableStat=false
enableMVCC=false
[exec.sub.token]
saveTokenTxList=false
`
CPFT_RUNMAIN_BLOCK = `package main
var ${PROJECTNAME} = `
// 生成项目运行主程序的模板 xxx.go
// 顶部还需要加上package main
//var bityuan = `CPFT_RUNMAIN`
CPFT_RUNMAIN = `TestNet=false
[blockchain]
defCacheSize=128
maxFetchBlockNum=128
timeoutSeconds=5
batchBlockNum=128
driver="leveldb"
isStrongConsistency=false
singleMode=false
[p2p]
enable=true
serverStart=true
msgCacheSize=10240
driver="leveldb"
[mempool]
poolCacheSize=102400
minTxFee=100000
[consensus]
name="ticket"
minerstart=true
genesisBlockTime=1514533394
genesis="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
[mver.consensus]
fundKeyAddr = "1JmFaA6unrCFYEWPGRi7uuXY1KthTJxJEP"
coinReward = 18
coinDevFund = 12
ticketPrice = 10000
powLimitBits = "0x1f00ffff"
retargetAdjustmentFactor = 4
futureBlockTime = 15
ticketFrozenTime = 43200
ticketWithdrawTime = 172800
ticketMinerWaitTime = 7200
maxTxNumber = 1500
targetTimespan = 2160
targetTimePerBlock = 15
[consensus.sub.ticket]
genesisBlockTime=1526486816
[[consensus.sub.ticket.genesis]]
minerAddr="184wj4nsgVxKyz2NhM3Yb5RK5Ap6AFRFq2"
returnAddr="1FB8L3DykVF7Y78bRfUrRcMZwesKue7CyR"
count=3000
[[consensus.sub.ticket.genesis]]
minerAddr="1M4ns1eGHdHak3SNc2UTQB75vnXyJQd91s"
returnAddr="1Lw6QLShKVbKM6QvMaCQwTh5Uhmy4644CG"
count=3000
[[consensus.sub.ticket.genesis]]
minerAddr="19ozyoUGPAQ9spsFiz9CJfnUCFeszpaFuF"
returnAddr="1PSYYfCbtSeT1vJTvSKmQvhz8y6VhtddWi"
count=3000
[[consensus.sub.ticket.genesis]]
minerAddr="1MoEnCDhXZ6Qv5fNDGYoW6MVEBTBK62HP2"
returnAddr="1BG9ZoKtgU5bhKLpcsrncZ6xdzFCgjrZud"
count=3000
[[consensus.sub.ticket.genesis]]
minerAddr="1FjKcxY7vpmMH6iB5kxNYLvJkdkQXddfrp"
returnAddr="1G7s64AgX1ySDcUdSW5vDa8jTYQMnZktCd"
count=3000
[[consensus.sub.ticket.genesis]]
minerAddr="12T8QfKbCRBhQdRfnAfFbUwdnH7TDTm4vx"
returnAddr="1FiDC6XWHLe7fDMhof8wJ3dty24f6aKKjK"
count=3000
[[consensus.sub.ticket.genesis]]
minerAddr="1bgg6HwQretMiVcSWvayPRvVtwjyKfz1J"
returnAddr="1AMvuuQ7V7FPQ4hkvHQdgNWy8wVL4d4hmp"
count=3000
[[consensus.sub.ticket.genesis]]
minerAddr="1EwkKd9iU1pL2ZwmRAC5RrBoqFD1aMrQ2"
returnAddr="1ExRRLoJXa8LzXdNxnJvBkVNZpVw3QWMi4"
count=3000
[[consensus.sub.ticket.genesis]]
minerAddr="1HFUhgxarjC7JLru1FLEY6aJbQvCSL58CB"
returnAddr="1KNGHukhbBnbWWnMYxu1C7YMoCj45Z3amm"
count=3000
[[consensus.sub.ticket.genesis]]
minerAddr="1C9M1RCv2e9b4GThN9ddBgyxAphqMgh5zq"
returnAddr="1AH9HRd4WBJ824h9PP1jYpvRZ4BSA4oN6Y"
count=4733
[store]
name="mavl"
driver="leveldb"
[wallet]
minFee=100000
driver="leveldb"
signType="secp256k1"
[exec]
isFree=false
minExecFee=100000
[exec.sub.token]
#配置一个空值,防止配置文件被覆盖
tokenApprs = []
[exec.sub.relay]
genesis="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
[exec.sub.manage]
superManager=[
"1JmFaA6unrCFYEWPGRi7uuXY1KthTJxJEP",
]
#系统中所有的fork,默认用chain33的测试网络的
#但是我们可以替换
[fork.system]
ForkChainParamV1= 0
ForkCheckTxDup=0
ForkBlockHash= 1
ForkMinerTime= 0
ForkTransferExec= 100000
ForkExecKey= 200000
ForkTxGroup= 200000
ForkResetTx0= 200000
ForkWithdraw= 200000
ForkExecRollback= 450000
ForkCheckBlockTime=1200000
ForkTxHeight= -1
ForkTxGroupPara= -1
ForkChainParamV2= -1
[fork.sub.coins]
Enable=0
[fork.sub.ticket]
Enable=0
ForkTicketId = 1200000
[fork.sub.retrieve]
Enable=0
ForkRetrive=0
[fork.sub.hashlock]
Enable=0
[fork.sub.manage]
Enable=0
ForkManageExec=100000
[fork.sub.token]
Enable=0
ForkTokenBlackList= 0
ForkBadTokenSymbol= 0
ForkTokenPrice= 300000
[fork.sub.trade]
Enable=0
ForkTradeBuyLimit= 0
ForkTradeAsset= -1
`
// 生成项目Makefile文件的模板 Makefile
CPFT_MAKEFILE = `
CHAIN33=github.com/33cn/chain33
CHAIN33_PATH=vendor/${CHAIN33}
all: vendor proto build
build:
go build -i -o ${PROJECTNAME}
go build -i -o ${PROJECTNAME}-cli ${PROJECTPATH}/cli
vendor:
make update
make updatevendor
proto:
cd ${GOPATH}/src/${PROJECTPATH}/plugin/dapp/${EXECNAME}/proto && sh create_protobuf.sh
update:
go get -u -v github.com/kardianos/govendor
rm -rf ${CHAIN33_PATH}
git clone --depth 1 -b master https://${CHAIN33}.git ${CHAIN33_PATH}
rm -rf vendor/${CHAIN33}/.git
rm -rf vendor/${CHAIN33}/vendor/github.com/apache/thrift/tutorial/erl/
cp -Rf vendor/${CHAIN33}/vendor/* vendor/
rm -rf vendor/${CHAIN33}/vendor
govendor init
go build -i -o tool github.com/33cn/plugin/vendor/github.com/33cn/chain33/cmd/tools
./tool import --path "plugin" --packname "${PROJECTPATH}/plugin" --conf "plugin/plugin.toml"
updatevendor:
govendor add +e
govendor fetch -v +m
clean:
@rm -rf vendor
@rm -rf datadir
@rm -rf logs
@rm -rf wallet
@rm -rf grpc33.log
@rm -rf ${PROJECTNAME}
@rm -rf ${PROJECTNAME}-cli
@rm -rf tool
@rm -rf plugin/init.go
@rm -rf plugin/consensus/init
@rm -rf plugin/dapp/init
@rm -rf plugin/crypto/init
@rm -rf plugin/store/init
`
// 生成 .travis.yml 文件模板
CPFT_TRAVIS_YML = `
language: go
go:
- "1.9"
- master
`
// 生成 plugin/plugin.toml的文件模板
CPFT_PLUGIN_TOML = `
# type字段仅支持 consensus dapp store
[dapp-ticket]
gitrepo = "github.com/33cn/plugin/plugin/dapp/ticket"
[consensus-ticket]
gitrepo = "github.com/33cn/plugin/plugin/consensus/ticket"
[dapp-retrieve]
gitrepo = "github.com/33cn/plugin/plugin/dapp/retrieve"
[dapp-hashlock]
gitrepo = "github.com/33cn/plugin/plugin/dapp/hashlock"
[dapp-token]
gitrepo = "github.com/33cn/plugin/plugin/dapp/token"
[dapp-trade]
gitrepo = "github.com/33cn/plugin/plugin/dapp/trade"
`
// 项目 cli/main.go 文件模板
CPFT_CLI_MAIN = `package main
import (
_ "${PROJECTPATH}/plugin"
_ "github.com/33cn/chain33/system"
"github.com/33cn/chain33/util/cli"
)
func main() {
cli.Run("", "")
}
`
// plugin/dapp/xxxx/commands/cmd.go文件的模板c
CPFT_DAPP_COMMANDS = `package commands
import (
"github.com/spf13/cobra"
)
func Cmd() *cobra.Command {
return nil
}`
// plugin/dapp/xxxx/plugin.go文件的模板
CPFT_DAPP_PLUGIN = `package ${PROJECTNAME}
import (
"github.com/33cn/chain33/pluginmgr"
"${PROJECTPATH}/plugin/dapp/${PROJECTNAME}/commands"
"${PROJECTPATH}/plugin/dapp/${PROJECTNAME}/executor"
"${PROJECTPATH}/plugin/dapp/${PROJECTNAME}/types"
)
func init() {
pluginmgr.Register(&pluginmgr.PluginBase{
Name: types.${EXECNAME_FB}X,
ExecName: executor.GetName(),
Exec: executor.Init,
Cmd: commands.Cmd,
RPC: nil,
})
}
`
// plugin/dapp/xxxx/executor/xxxx.go文件模板
CPFT_DAPP_EXEC = `package executor
import (
log "github.com/inconshreveable/log15"
drivers "gitlab.33.cn/chain33/chain33/system/dapp"
"gitlab.33.cn/chain33/chain33/types"
)
var clog = log.New("module", "execs.${EXECNAME}")
var driverName = "${EXECNAME}"
func init() {
ety := types.LoadExecutorType(driverName)
if ety != nil {
ety.InitFuncList(types.ListMethod(&${CLASSNAME}{}))
}
}
func Init(name string, sub []byte) {
ety := types.LoadExecutorType(driverName)
if ety != nil {
ety.InitFuncList(types.ListMethod(&${CLASSNAME}{}))
}
clog.Debug("register ${EXECNAME} execer")
drivers.Register(GetName(), new${CLASSNAME}, types.GetDappFork(driverName, "Enable"))
}
func GetName() string {
return new${CLASSNAME}().GetName()
}
type ${CLASSNAME} struct {
drivers.DriverBase
}
func new${CLASSNAME}() drivers.Driver {
n := &${CLASSNAME}{}
n.SetChild(n)
n.SetIsFree(true)
n.SetExecutorType(types.LoadExecutorType(driverName))
return n
}
func (this *${CLASSNAME}) GetDriverName() string {
return driverName
}
func (this *${CLASSNAME}) CheckTx(tx *types.Transaction, index int) error {
return nil
}
`
// plugin/dapp/xxxx/proto/create_protobuf.sh文件模板
CPFT_DAPP_CREATEPB = `#!/bin/sh
protoc --go_out=plugins=grpc:../types ./*.proto --proto_path=.
`
// plugin/dapp/xxxx/proto/Makefile 文件模板
CPFT_DAPP_MAKEFILE = `all:
sh ./create_protobuf.sh
`
// plugin/dapp/xxxx/proto/xxxx.proto的文件模板
CPFT_DAPP_PROTO = `syntax = "proto3";
package types;
message ${ACTIONNAME} {
int32 ty = 1;
oneof value {
${ACTIONNAME}None none = 2;
}
}
message ${ACTIONNAME}None {
}
`
// plugin/dapp/xxxx/types/types.go的文件模板cd
CPFT_DAPP_TYPEFILE = `package types
import (
"gitlab.33.cn/chain33/chain33/types"
)
var (
${EXECNAME_FB}X = "${EXECNAME}"
Execer${EXECNAME_FB} = []byte(${EXECNAME_FB}X)
actionName = map[string]int32{}
logmap = map[int64]*types.LogInfo{}
)
func init() {
types.AllowUserExec = append(types.AllowUserExec, Execer${EXECNAME_FB})
types.RegistorExecutor("${EXECNAME}", NewType())
types.RegisterDappFork(${EXECNAME_FB}X, "Enable", 0)
}
type ${CLASSTYPENAME} struct {
types.ExecTypeBase
}
func NewType() *${CLASSTYPENAME} {
c := &${CLASSTYPENAME}{}
c.SetChild(c)
return c
}
func (coins *${CLASSTYPENAME}) GetPayload() types.Message {
return &${ACTIONNAME}{}
}
func (coins *${CLASSTYPENAME}) GetName() string {
return ${EXECNAME_FB}X
}
func (coins *${CLASSTYPENAME}) GetLogMap() map[int64]*types.LogInfo {
return logmap
}
func (c *${CLASSTYPENAME}) GetTypeMap() map[string]int32 {
return actionName
}
`
)
//Copyright Fuzamei Corp. 2018 All Rights Reserved.
//Use of this source code is governed by a BSD-style
//license that can be found in the LICENSE file.
package strategy
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/33cn/chain33/util"
"github.com/33cn/chain33/cmd/tools/tasks"
"github.com/33cn/chain33/cmd/tools/types"
"github.com/pkg/errors"
)
// createPluginStrategy 根據模板配置文件,創建一個完整的項目工程
type createPluginStrategy struct {
strategyBasic
gopath string
projName string // 项目名称
execName string // 项目中实现的执行器名称
execNameFB string
className string
classTypeName string
classActionName string
outRootPath string // 项目生成的根目录
projectPath string // 生成的项目路径,是绝对路径
}
func (c *createPluginStrategy) Run() error {
fmt.Println("Begin run chain33 create plugin project mode.")
defer fmt.Println("Run chain33 create plugin project mode finish.")
if err := c.initMember(); err != nil {
return err
}
return c.rumImpl()
}
func (c *createPluginStrategy) initMember() error {
gopath := os.Getenv("GOPATH")
if len(gopath) <= 0 {
return errors.New("Can't find GOPATH")
}
c.gopath = gopath
c.outRootPath = filepath.Join(gopath, "/src/github.com/33cn")
c.projName, _ = c.getParam(types.KeyProjectName)
c.execName, _ = c.getParam(types.KeyExecutorName)
c.className, _ = c.getParam(types.KeyClassName)
c.projectPath = fmt.Sprintf("%s/%s", c.outRootPath, c.projName)
c.execNameFB, _ = util.MakeStringToUpper(c.execName, 0, 1)
c.classTypeName = c.execNameFB + "Type"
c.classActionName = c.execNameFB + "Action"
return nil
}
func (c *createPluginStrategy) rumImpl() error {
var err error
tasks := c.buildTask()
for _, task := range tasks {
err = task.Execute()
if err != nil {
mlog.Error("Execute command failed.", "error", err, "taskname", task.GetName())
break
}
}
return err
}
func (c *createPluginStrategy) buildTask() []tasks.Task {
// 获取项目相对于gopath/src中的目录路径
goprojpath := strings.Replace(c.projectPath, c.gopath+"/src/", "", -1)
taskSlice := make([]tasks.Task, 0)
taskSlice = append(taskSlice,
&tasks.CreateFileFromStrTemplateTask{
SourceStr: CPFT_MAIN_GO,
OutputFile: fmt.Sprintf("%s/main.go", c.projectPath),
ReplaceKeyPairs: map[string]string{
types.TagProjectName: c.projName,
types.TagProjectPath: goprojpath,
},
},
&tasks.CreateFileFromStrTemplateTask{
SourceStr: CPFT_CFG_TOML,
OutputFile: fmt.Sprintf("%s/%s.toml", c.projectPath, c.projName),
ReplaceKeyPairs: map[string]string{
types.TagProjectName: c.projName,
},
},
&tasks.CreateFileFromStrTemplateTask{
SourceStr: CPFT_RUNMAIN,
BlockStrBegin: CPFT_RUNMAIN_BLOCK + "`",
BlockStrEnd: "`",
OutputFile: fmt.Sprintf("%s/%s.go", c.projectPath, c.projName),
ReplaceKeyPairs: map[string]string{
types.TagProjectName: c.projName,
},
},
&tasks.CreateFileFromStrTemplateTask{
SourceStr: CPFT_MAKEFILE,
OutputFile: fmt.Sprintf("%s/Makefile", c.projectPath),
ReplaceKeyPairs: map[string]string{
types.TagProjectName: c.projName,
types.TagProjectPath: goprojpath,
types.TagGoPath: c.gopath,
types.TagExecName: c.execName,
},
},
&tasks.CreateFileFromStrTemplateTask{
SourceStr: CPFT_TRAVIS_YML,
OutputFile: fmt.Sprintf("%s/.travis.yml", c.projectPath),
ReplaceKeyPairs: map[string]string{
types.TagProjectName: c.projName,
},
},
&tasks.CreateFileFromStrTemplateTask{
SourceStr: CPFT_PLUGIN_TOML,
OutputFile: fmt.Sprintf("%s/plugin/plugin.toml", c.projectPath),
ReplaceKeyPairs: map[string]string{
types.TagProjectName: c.projName,
},
},
&tasks.CreateFileFromStrTemplateTask{
SourceStr: CPFT_CLI_MAIN,
OutputFile: fmt.Sprintf("%s/cli/main.go", c.projectPath),
ReplaceKeyPairs: map[string]string{
types.TagProjectName: c.projName,
types.TagProjectPath: goprojpath,
},
},
&tasks.CreateFileFromStrTemplateTask{
SourceStr: CPFT_DAPP_COMMANDS,
OutputFile: fmt.Sprintf("%s/plugin/dapp/%s/commands/cmd.go", c.projectPath, c.execName),
ReplaceKeyPairs: map[string]string{
types.TagProjectName: c.projName,
},
},
&tasks.CreateFileFromStrTemplateTask{
SourceStr: CPFT_DAPP_PLUGIN,
OutputFile: fmt.Sprintf("%s/plugin/dapp/%s/plugin.go", c.projectPath, c.projName),
ReplaceKeyPairs: map[string]string{
types.TagProjectName: c.projName,
types.TagExecNameFB: c.execNameFB,
types.TagProjectPath: goprojpath,
},
},
&tasks.CreateFileFromStrTemplateTask{
SourceStr: CPFT_DAPP_EXEC,
OutputFile: fmt.Sprintf("%s/plugin/dapp/%s/executor/%s.go", c.projectPath, c.projName, c.execName),
ReplaceKeyPairs: map[string]string{
types.TagProjectName: c.projName,
types.TagExecName: c.execName,
types.TagClassName: c.className,
},
},
&tasks.CreateFileFromStrTemplateTask{
SourceStr: CPFT_DAPP_CREATEPB,
OutputFile: fmt.Sprintf("%s/plugin/dapp/%s/proto/create_protobuf.sh", c.projectPath, c.projName),
ReplaceKeyPairs: map[string]string{},
},
&tasks.CreateFileFromStrTemplateTask{
SourceStr: CPFT_DAPP_MAKEFILE,
OutputFile: fmt.Sprintf("%s/plugin/dapp/%s/proto/Makefile", c.projectPath, c.projName),
ReplaceKeyPairs: map[string]string{},
},
&tasks.CreateFileFromStrTemplateTask{
SourceStr: CPFT_DAPP_PROTO,
OutputFile: fmt.Sprintf("%s/plugin/dapp/%s/proto/%s.proto", c.projectPath, c.projName, c.execName),
ReplaceKeyPairs: map[string]string{
types.TagActionName: c.classActionName,
},
},
&tasks.CreateFileFromStrTemplateTask{
SourceStr: CPFT_DAPP_TYPEFILE,
OutputFile: fmt.Sprintf("%s/plugin/dapp/%s/types/types.go", c.projectPath, c.projName),
ReplaceKeyPairs: map[string]string{
types.TagExecNameFB: c.execNameFB,
types.TagExecName: c.execName,
types.TagClassTypeName: c.classTypeName,
types.TagActionName: c.classActionName,
},
},
// 需要将所有的go文件格式化以下
&tasks.FormatDappSourceTask{
OutputFolder: fmt.Sprintf("%s/%s/", c.outRootPath, c.projName),
},
)
return taskSlice
}
/*
* Copyright Fuzamei Corp. 2018 All Rights Reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
package tasks
import (
"fmt"
"strings"
"github.com/33cn/chain33/util"
)
// CreateFileFromStrTemplateTask 从指定的模板字符串中创建目标文件的任务
type CreateFileFromStrTemplateTask struct {
TaskBase
SourceStr string
OutputFile string
BlockStrBegin string // Block会将SourceStr包含在内部
BlockStrEnd string
ReplaceKeyPairs map[string]string
fileContent string
}
//GetName 获取name
func (c *CreateFileFromStrTemplateTask) GetName() string {
return "CreateFileFromStrTemplateTask"
}
//Execute 执行
func (c *CreateFileFromStrTemplateTask) Execute() error {
if len(c.BlockStrBegin) > 0 && len(c.BlockStrEnd) > 0 {
c.SourceStr = fmt.Sprintf("%s%s%s", c.BlockStrBegin, c.SourceStr, c.BlockStrEnd)
}
c.fileContent = c.SourceStr
for key, value := range c.ReplaceKeyPairs {
c.fileContent = strings.Replace(c.fileContent, key, value, -1)
}
if err := util.MakeDir(c.OutputFile); err != nil {
return err
}
util.DeleteFile(c.OutputFile)
len, err := util.WriteStringToFile(c.OutputFile, c.fileContent)
if err == nil {
mlog.Info("Create file success.", "file", c.OutputFile, "file len", len)
} else {
mlog.Info("Create file falied.", "error", err)
}
return err
}
#!/bin/bash
# shellcheck disable=SC2207
set +e
OP="${1}"
path="${2}"
function filterLinter() {
res=$(gometalinter.v2 -t --sort=linter --enable-gc --deadline=2m --disable-all \
--enable=gofmt \
--enable=gosimple \
--enable=deadcode \
--enable=unconvert \
--enable=interfacer \
--enable=varcheck \
--enable=structcheck \
--enable=goimports \
--enable=misspell \
--vendor ./...)
# --enable=staticcheck \
# --enable=gocyclo \
# --enable=staticcheck \
# --enable=golint \
# --enable=unused \
# --enable=gotype \
# --enable=gotypex \
if [[ ${#res} -gt "0" ]]; then
resNoSpace=$(echo "${res}" | tr ' ' '@')
array=($(echo "${resNoSpace}" | tr '\n' '\n'))
str=""
for var in ${array[*]}; do
if ! [[ $var =~ "underscores" ]]; then
str="${str}""${var}""\\n"
fi
done
res=""
res=$(echo "${str}" | tr '@' ' ')
fi
if [[ ${#res} -gt "0" ]]; then
echo -e "${res}"
exit 1
fi
}
function testLinter() {
cd "${path}" >/dev/null || exit
gometalinter.v2 -t --sort=linter --enable-gc --deadline=2m --disable-all \
--enable=gofmt \
--enable=gosimple \
--enable=deadcode \
--enable=unconvert \
--enable=interfacer \
--enable=varcheck \
--enable=structcheck \
--enable=goimports \
--enable=vet \
--enable=golint \
--enable=ineffassign \
--vendor ./...
cd - >/dev/null || exit
}
function main() {
if [ "${OP}" == "filter" ]; then
filterLinter
elif [ "${OP}" == "test" ]; then
testLinter
fi
}
# run script
main
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of policy source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package wallet
import (
"sync"
"github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/types"
wcom "github.com/33cn/chain33/wallet/common"
)
const (
walletBizPolicyX = "walletBizPolicy"
)
func init() {
wcom.RegisterPolicy(walletBizPolicyX, newPolicy())
}
func newPolicy() wcom.WalletBizPolicy {
ret := &walletBizPlicy{
mtx: &sync.Mutex{},
}
return ret
}
// 默认的钱包业务实现
type walletBizPlicy struct {
mtx *sync.Mutex
walletOperate wcom.WalletOperate
}
func (policy *walletBizPlicy) Init(walletBiz wcom.WalletOperate, sub []byte) {
policy.setWalletOperate(walletBiz)
}
func (policy *walletBizPlicy) setWalletOperate(walletBiz wcom.WalletOperate) {
policy.mtx.Lock()
defer policy.mtx.Unlock()
policy.walletOperate = walletBiz
}
func (policy *walletBizPlicy) getWalletOperate() wcom.WalletOperate {
policy.mtx.Lock()
defer policy.mtx.Unlock()
return policy.walletOperate
}
func (policy *walletBizPlicy) OnAddBlockTx(block *types.BlockDetail, tx *types.Transaction, index int32, dbbatch db.Batch) *types.WalletTxDetail {
return nil
}
func (policy *walletBizPlicy) OnDeleteBlockTx(block *types.BlockDetail, tx *types.Transaction, index int32, dbbatch db.Batch) *types.WalletTxDetail {
return nil
}
func (policy *walletBizPlicy) SignTransaction(key crypto.PrivKey, req *types.ReqSignRawTx) (needSysSign bool, signtx string, err error) {
needSysSign = true
return
}
func (policy *walletBizPlicy) OnCreateNewAccount(acc *types.Account) {
wg := policy.getWalletOperate().GetWaitGroup()
wg.Add(1)
go policy.rescanReqTxDetailByAddr(acc.Addr, wg)
}
func (policy *walletBizPlicy) OnImportPrivateKey(acc *types.Account) {
wg := policy.getWalletOperate().GetWaitGroup()
wg.Add(1)
go policy.rescanReqTxDetailByAddr(acc.Addr, wg)
}
func (policy *walletBizPlicy) OnWalletLocked() {
}
func (policy *walletBizPlicy) OnWalletUnlocked(WalletUnLock *types.WalletUnLock) {
}
func (policy *walletBizPlicy) OnAddBlockFinish(block *types.BlockDetail) {
}
func (policy *walletBizPlicy) OnDeleteBlockFinish(block *types.BlockDetail) {
}
func (policy *walletBizPlicy) OnClose() {
}
func (policy *walletBizPlicy) OnSetQueueClient() {
}
func (policy *walletBizPlicy) Call(funName string, in types.Message) (ret types.Message, err error) {
err = types.ErrNotSupport
return
}
//从blockchain模块同步addr参与的所有交易详细信息
func (policy *walletBizPlicy) rescanReqTxDetailByAddr(addr string, wg *sync.WaitGroup) {
defer wg.Done()
policy.reqTxDetailByAddr(addr)
}
//从blockchain模块同步addr参与的所有交易详细信息
func (policy *walletBizPlicy) reqTxDetailByAddr(addr string) {
if len(addr) == 0 {
walletlog.Error("reqTxDetailByAddr input addr is nil!")
return
}
var txInfo types.ReplyTxInfo
i := 0
operater := policy.getWalletOperate()
for {
//首先从blockchain模块获取地址对应的所有交易hashs列表,从最新的交易开始获取
var ReqAddr types.ReqAddr
ReqAddr.Addr = addr
ReqAddr.Flag = 0
ReqAddr.Direction = 0
ReqAddr.Count = int32(MaxTxHashsPerTime)
if i == 0 {
ReqAddr.Height = -1
ReqAddr.Index = 0
} else {
ReqAddr.Height = txInfo.GetHeight()
ReqAddr.Index = txInfo.GetIndex()
}
i++
ReplyTxInfos, err := operater.GetAPI().GetTransactionByAddr(&ReqAddr)
if err != nil {
walletlog.Error("reqTxDetailByAddr", "GetTransactionByAddr error", err, "addr", addr)
return
}
if ReplyTxInfos == nil {
walletlog.Info("reqTxDetailByAddr ReplyTxInfos is nil")
return
}
txcount := len(ReplyTxInfos.TxInfos)
var ReqHashes types.ReqHashes
ReqHashes.Hashes = make([][]byte, len(ReplyTxInfos.TxInfos))
for index, ReplyTxInfo := range ReplyTxInfos.TxInfos {
ReqHashes.Hashes[index] = ReplyTxInfo.GetHash()
txInfo.Hash = ReplyTxInfo.GetHash()
txInfo.Height = ReplyTxInfo.GetHeight()
txInfo.Index = ReplyTxInfo.GetIndex()
}
operater.GetTxDetailByHashs(&ReqHashes)
if txcount < int(MaxTxHashsPerTime) {
return
}
}
}
The MIT License (MIT)
Copyright (c) 2015 Dean Karn
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.
package github
import (
"crypto/hmac"
"crypto/sha1"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
)
// parse errors
var (
ErrEventNotSpecifiedToParse = errors.New("no Event specified to parse")
ErrInvalidHTTPMethod = errors.New("invalid HTTP Method")
ErrMissingGithubEventHeader = errors.New("missing X-GitHub-Event Header")
ErrMissingHubSignatureHeader = errors.New("missing X-Hub-Signature Header")
ErrEventNotFound = errors.New("event not defined to be parsed")
ErrParsingPayload = errors.New("error parsing payload")
ErrHMACVerificationFailed = errors.New("HMAC verification failed")
)
// Event defines a GitHub hook event type
type Event string
// GitHub hook types
const (
CommitCommentEvent Event = "commit_comment"
CreateEvent Event = "create"
DeleteEvent Event = "delete"
DeploymentEvent Event = "deployment"
DeploymentStatusEvent Event = "deployment_status"
ForkEvent Event = "fork"
GollumEvent Event = "gollum"
InstallationEvent Event = "installation"
IntegrationInstallationEvent Event = "integration_installation"
IssueCommentEvent Event = "issue_comment"
IssuesEvent Event = "issues"
LabelEvent Event = "label"
MemberEvent Event = "member"
MembershipEvent Event = "membership"
MilestoneEvent Event = "milestone"
OrganizationEvent Event = "organization"
OrgBlockEvent Event = "org_block"
PageBuildEvent Event = "page_build"
PingEvent Event = "ping"
ProjectCardEvent Event = "project_card"
ProjectColumnEvent Event = "project_column"
ProjectEvent Event = "project"
PublicEvent Event = "public"
PullRequestEvent Event = "pull_request"
PullRequestReviewEvent Event = "pull_request_review"
PullRequestReviewCommentEvent Event = "pull_request_review_comment"
PushEvent Event = "push"
ReleaseEvent Event = "release"
RepositoryEvent Event = "repository"
StatusEvent Event = "status"
TeamEvent Event = "team"
TeamAddEvent Event = "team_add"
WatchEvent Event = "watch"
)
// EventSubtype defines a GitHub Hook Event subtype
type EventSubtype string
// GitHub hook event subtypes
const (
NoSubtype EventSubtype = ""
BranchSubtype EventSubtype = "branch"
TagSubtype EventSubtype = "tag"
PullSubtype EventSubtype = "pull"
IssueSubtype EventSubtype = "issues"
)
// Option is a configuration option for the webhook
type Option func(*Webhook) error
// Options is a namespace var for configuration options
var Options = WebhookOptions{}
// WebhookOptions is a namespace for configuration option methods
type WebhookOptions struct{}
// Secret registers the GitHub secret
func (WebhookOptions) Secret(secret string) Option {
return func(hook *Webhook) error {
hook.secret = secret
return nil
}
}
// Webhook instance contains all methods needed to process events
type Webhook struct {
secret string
}
// New creates and returns a WebHook instance denoted by the Provider type
func New(options ...Option) (*Webhook, error) {
hook := new(Webhook)
for _, opt := range options {
if err := opt(hook); err != nil {
return nil, errors.New("Error applying Option")
}
}
return hook, nil
}
// Parse verifies and parses the events specified and returns the payload object or an error
func (hook Webhook) Parse(r *http.Request, events ...Event) (interface{}, error) {
defer func() {
_, _ = io.Copy(ioutil.Discard, r.Body)
_ = r.Body.Close()
}()
if len(events) == 0 {
return nil, ErrEventNotSpecifiedToParse
}
if r.Method != http.MethodPost {
return nil, ErrInvalidHTTPMethod
}
event := r.Header.Get("X-GitHub-Event")
if event == "" {
return nil, ErrMissingGithubEventHeader
}
gitHubEvent := Event(event)
var found bool
for _, evt := range events {
if evt == gitHubEvent {
found = true
break
}
}
// event not defined to be parsed
if !found {
return nil, ErrEventNotFound
}
payload, err := ioutil.ReadAll(r.Body)
if err != nil || len(payload) == 0 {
return nil, ErrParsingPayload
}
// If we have a Secret set, we should check the MAC
if len(hook.secret) > 0 {
signature := r.Header.Get("X-Hub-Signature")
if len(signature) == 0 {
return nil, ErrMissingHubSignatureHeader
}
mac := hmac.New(sha1.New, []byte(hook.secret))
_, _ = mac.Write(payload)
expectedMAC := hex.EncodeToString(mac.Sum(nil))
if !hmac.Equal([]byte(signature[5:]), []byte(expectedMAC)) {
return nil, ErrHMACVerificationFailed
}
}
switch gitHubEvent {
case CommitCommentEvent:
var pl CommitCommentPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case CreateEvent:
var pl CreatePayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case DeleteEvent:
var pl DeletePayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case DeploymentEvent:
var pl DeploymentPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case DeploymentStatusEvent:
var pl DeploymentStatusPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case ForkEvent:
var pl ForkPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case GollumEvent:
var pl GollumPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case InstallationEvent, IntegrationInstallationEvent:
var pl InstallationPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case IssueCommentEvent:
var pl IssueCommentPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case IssuesEvent:
var pl IssuesPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case LabelEvent:
var pl LabelPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case MemberEvent:
var pl MemberPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case MembershipEvent:
var pl MembershipPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case MilestoneEvent:
var pl MilestonePayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case OrganizationEvent:
var pl OrganizationPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case OrgBlockEvent:
var pl OrgBlockPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case PageBuildEvent:
var pl PageBuildPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case PingEvent:
var pl PingPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case ProjectCardEvent:
var pl ProjectCardPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case ProjectColumnEvent:
var pl ProjectColumnPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case ProjectEvent:
var pl ProjectPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case PublicEvent:
var pl PublicPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case PullRequestEvent:
var pl PullRequestPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case PullRequestReviewEvent:
var pl PullRequestReviewPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case PullRequestReviewCommentEvent:
var pl PullRequestReviewCommentPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case PushEvent:
var pl PushPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case ReleaseEvent:
var pl ReleasePayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case RepositoryEvent:
var pl RepositoryPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case StatusEvent:
var pl StatusPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case TeamEvent:
var pl TeamPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case TeamAddEvent:
var pl TeamAddPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case WatchEvent:
var pl WatchPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
default:
return nil, fmt.Errorf("unknown event %s", gitHubEvent)
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
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