33cn / chain33 Goto Github PK
View Code? Open in Web Editor NEW高度模块化, 遵循 KISS原则的区块链开发框架
Home Page: https://chain.33.cn
License: BSD 3-Clause "New" or "Revised" License
高度模块化, 遵循 KISS原则的区块链开发框架
Home Page: https://chain.33.cn
License: BSD 3-Clause "New" or "Revised" License
如题,分析一下可能的原因
Describe the bug
我在看代码的时候,发现在 ProcSendToAddress
函数中存在一个溢出,当设置 amount 足够大时,可以造成溢出
if !SendToAddress.IsToken {
if Balance < amount+wallet.FeeAmount {
return nil, types.ErrInsufficientBalance
}
}
To Reproduce
执行下面的脚本可以触发
sendTrans = "{\"method\": \"Chain33.SendToAddress\",\"params\": [{\"From\": \"1CbEVT9RnM5oZhWMj4fxUrJX94VtRotzvs\",\"To\": \"1GhMZ7vpEEGLUmxcf8KRNedjpKZYFus9dJ\",\"amount\": 9223372036854775807}],\"id\": 0}"
print sendTrans
req2 = requests.post("http://localhost:8801",data=sendTrans)
print 'sendTrans',req2.text
Expected behavior
应该抛出 amountErr 异常,而不是交易哈希
manage目前没有实现通过createTransaction rpc接口去创建tx, 需要支持这一操作
更新到最新版本后cli version显示为6.0.1
实际最新版本应为6.0.2
我们用工具检查出来了错误拼写 和 无效 assign 的问题。
详细查看:
https://goreportcard.com/report/github.com/33cn/chain33#misspell
https://goreportcard.com/report/github.com/33cn/chain33#ineffassign
enableMavlPrefix=false
enableMVCC=false
enableMavlPrune=false
pruneHeight=10000
Describe the bug
when I sniffing the traffic, and send it again to the server, the server return me as follow:
{"id":0,"result":null,"error":"ErrTxExist"}
the traffic contains two method: SignRawTx and Chain33.SendTransaction, but i notice that the SignRawTx method contains my -k
arg as addr
:
./chain33-cli send bty transfer -a 1000 -t 1GhMZ7vpEEGLUmxcf8KRNedjpKZYFus9dJ -n \"test for transfer bty\" -k 1CbEVT9RnM5oZhWMj4fxUrJX94VtRotzvs
"addr": "1CbEVT9RnM5oZhWMj4fxUrJX94VtRotzvs",
"txHex": ",
"expire": "120s"
So i think that it is signed in server side and I can modify something to replay the transaction.
Then i modify the expire
to 121s
to invoke SignRawTx, it send me a result
which is different from before.
After that I invoke the SendTransaction and it return me a transaction hash, state is ExecOK !
To Reproduce
from scapy.all import *
import json,os,threading,requests
class myThread1(threading.Thread):
def run(self):
os.system(
"./chain33-cli send bty transfer -a 1000 -t 1GhMZ7vpEEGLUmxcf8KRNedjpKZYFus9dJ -n \"test for transfer bty\" -k 1CbEVT9RnM5oZhWMj4fxUrJX94VtRotzvs")
class myThread2(threading.Thread):
def run(self):
dpkt = sniff(iface='lo0', count=25, filter="tcp and ( port 8801)")
obj = []
for item in dpkt:
if 'method' in str(item):
obj.append(str(item[TCP])[181:])
req1 = requests.post("http://localhost:8801",data=obj[0].replace("120s","121s"))
print 'sign',obj[0]
hs = json.loads(req1.text)['result']
print 'result',hs
sendTrans = "{\"method\": \"Chain33.SendTransaction\",\"params\": [{\"token\": \"BTY\",\"data\": \""+ hs +"\"}],\"id\": 0}"
print sendTrans
req2 = requests.post("http://localhost:8801",data=sendTrans.replace("120s","121s"))
print 'sendTrans',req2.text
thread1 = myThread1()
thread2 = myThread2()
thread2.start()
thread1.start()
Expected behavior
it should signed in client side.
localdb 的version 目前直接写死在代码里面,不够灵活,也不能支持不同的链不同的版本号。
代码在 common/version , 可以把localdb 的version 通过配置文件来配置,这样更加灵活。
目前开发平行链合约时,每个合约都需要自己创建rpc连接,去操作主链相关信息;
建议将此能力进行封装,提供统一的主链访问通道和API,降低平行链合约的开发难度和工作量;
p2p默认端口是13802,可以增加一个配置项来修改这个默认的端口号
调用接口查询返回null
{"id":11,"result":{"addr":"13TTVDo8hY7GDG5Lgv492hVypukGCQNQYf","execAccount":null},"error":null}
应该是client在构造执行器名称时,没有将平行链的前缀带进去。
for _, exec := range types.AllowUserExec {
execer := string(exec)
params := &types.ReqBalance{
Addresses: addrs,
Execer: execer,
}
我们提供了一个 blockchain seq 的接口,可以通过轮询的方式,实时的获取数据。通过这个方式,可以把数据同步到mysql 中。这个程序可以完全独立于blockchain ,类似mysql 和 blockchain的一个桥梁。如果用go直接完成整个同步应该不会有问题,但是,个人认为我们应该运行 php, nodejs 之类的擅长网页开发的脚本来做这个事情,比较好的办法是,同步好一个快以后,通知 PHP ,Nodejs 的一个callback 接口,PHP 和 nodejs 通过这个callback 接口 进一步处理数据,处理完成后,返回ok,或者调用done接口,通知这个桥接程序,已经处理完成。通知总是按照 seq的顺序通知,如果客户端没有正确标记,就会一直通知这个seq。
localdb 改成可以在配置文件中配置。方便应用开发者升级数据库。
通过源码构造超过int64上限的交易时,数值错误
@icehawk-hyb
计算地址总接收时,未判断交易是否失败
@icehawk-hyb
添加多重签名地址
普通地址不能直接转账给多重签名地址
必须在支持多重签名地址的合约转账到多重签名地址
Describe the bug
If I send a transfer command and the amount with a big number, sometimes it will throw a AmountErr.
But when I review the code, I found that as follow.
amountInt64 := int64(math.Trunc((amount+0.0000001)*1e4)) * 1e4
So I make the amount = 1844674407370956,and it return me a transaction hash, not AmountErr.
To Reproduce
./chain33-cli send bty transfer -a 1844674407370956 -t 1GhMZ7vpEEGLUmxcf8KRNedjpKZYFus9dJ -n "test for transfer bty" -k 1CbEVT9RnM5oZhWMj4fxUrJX94VtRotzvs
Expected behavior
throw amountError
Screenshots
If applicable, add screenshots to help explain your problem.
localdb在机械硬盘上构造太慢,需要加速,减少刷盘
Describe the bug
本地solo测试时,余额被自动买成ticket
To Reproduce
Expected behavior
非ticket共识下,不应该启用ticket挖矿逻辑;
Screenshots
无
Desktop (please complete the following information):
在部分查询通过钱包接口调用钱包中client通道查询信息时,由于其他模块存在多线程调用的场景,所以可能在高频率调用的情况下出现数据竞争问题。
考虑在初始化时增加初始化是否完成的标记,只有初始化完成以后才允许执行一系列操作。
项目有一些新增feature和修改,一旦这些issue关闭,之前未关注的人便不感知。不可能每个人去翻git记录。有的新功能大家不会使用,还需要咨询相关开发人员。
新取的plugin代码,编译的chain33-cli
ubuntu@manager:~/game_paraChain$ ./chain33-cli block get -s 1 -e 2
ErrDecode
目前的随机数获取方式比较复杂,还需要考虑平行链分支,使用代码需要好几十行,比较不方便;
建议将随机数获取能力封装成本地API,放到DriverBase或其它什么地方,具体合约使用时,直接调用api即可。
目的是排队方式可以配置
目前的排队方式是按时间排队,不够灵活,将mempool的模式改成consensus和store那种可以配置的、可以在plugin修改排队方式的模式就比较灵活
具体设计中,考虑到只是修改排队方式的话,mempool当前的基本流程不变,只用对cache进行分离,插件可以修改cache里缓存池的数据结构,也可以通过对cache里的方法实现来控制排队方式的修改
建立一个随机数插件,各执行器可以通过封装好的消息,像获取区块高度那样,简单的从随机数插件获取一个Hash值
随机数插件,能够支持多种算法,根据配置文件选择具体的,与共识相关的算法,第一期支持ticket数据
日志:
t=2018-11-20T10:08:02+0800 lvl=info msg=EventAddBlockDetail module=blockchain height=32298 hash=2565eb1ebea289c65e11e0d15834766e6421de8af825ddf03b6e3378ecc9c7a9
t=2018-11-20T10:08:02+0800 lvl=eror msg="addBlockDetail parent hash no match" module=blockchain err=ErrBlockHashNoMatch bestHash=0xe74be80d69c0417ea0ca4d4838e0b4796afe69105bf84772249460f1094df89e blockHash=0x23a5f9e834488c0884ceb7fffed6ee4e6f14e35eb495db4c5f7c7e5aca109caa
addBlock=true height=32298
t=2018-11-20T10:08:02+0800 lvl=eror msg=addBlockDetail module=blockchain err=ErrBlockHashNoMatch
使用cli查询结果,blockHash和bestHash查询的节点block一致
root@ubuntu055-2:/home/lcj2# ./chain33-cli block view -s 0xe74be80d69c0417ea0ca4d4838e0b4796afe69105bf84772249460f1094df89e
{
"head":
{ "version": 0, "parentHash": "0xedf7213e03f98c69d700c10f3cc76b90417024d8d202c855b77add499a049188", "txHash": "0xf27e9046164a513467c48b609706d53d9a792d760fc36fc65b2a95adddc7c87d", "stateHash": "0x591874e1fda2e250f20a5a89897c23060e2e5fdf8170faab0376c16a5f01240b", "height": 32297, "blockTime": 1542620076, "txCount": 4, "hash": "0x23a5f9e834488c0884ceb7fffed6ee4e6f14e35eb495db4c5f7c7e5aca109caa", "difficulty": 505287814 }
,
"txCount": 4,
"txHashes": [
"0x35eccb79dcf12f940990621e401aaefc7a523e7eedee7b183032b7f55147d073",
"0xfcf014282ed95209393b943230e64483dd0906761a9e7f2b98754c2ce0fb4160",
"0xdc76081b95e5b27544927128864bbbb9b3cba92f6d15f6390f5eda6750859e3c",
"0x932de9bd54a49990ebfdc11b13ff13bcf25e53f2cbff5739a60af6d348c5e545"
]
}
root@ubuntu055-2:/home/lcj2# ./chain33-cli block view -s 0x23a5f9e834488c0884ceb7fffed6ee4e6f14e35eb495db4c5f7c7e5aca109caa
{
"head":
{ "version": 0, "parentHash": "0xedf7213e03f98c69d700c10f3cc76b90417024d8d202c855b77add499a049188", "txHash": "0xf27e9046164a513467c48b609706d53d9a792d760fc36fc65b2a95adddc7c87d", "stateHash": "0x591874e1fda2e250f20a5a89897c23060e2e5fdf8170faab0376c16a5f01240b", "height": 32297, "blockTime": 1542620076, "txCount": 4, "hash": "0x23a5f9e834488c0884ceb7fffed6ee4e6f14e35eb495db4c5f7c7e5aca109caa", "difficulty": 505287814 }
,
"txCount": 4,
"txHashes": [
"0x35eccb79dcf12f940990621e401aaefc7a523e7eedee7b183032b7f55147d073",
"0xfcf014282ed95209393b943230e64483dd0906761a9e7f2b98754c2ce0fb4160",
"0xdc76081b95e5b27544927128864bbbb9b3cba92f6d15f6390f5eda6750859e3c",
"0x932de9bd54a49990ebfdc11b13ff13bcf25e53f2cbff5739a60af6d348c5e545"
]
}
目前执行器单元测试还没有一个通用好到办法,可以考虑加一个范例,做一下单元测试。
可以测试 exec 和 local del local, 测试回滚状态的 数据库是否正确。
可以考虑用一个专门用于测试的 Localdb 和 statedb
Describe the bug
我在看代码的时候,发现在 parseExpire 函数中存在一处溢出。
func (wallet *Wallet) parseExpire(expire string) (int64, error) {
if len(expire) == 0 {
return 0, errors.New("Expire string should not be empty")
}
if expire[0] == 'H' && expire[1] == ':' {
txHeight, err := strconv.ParseInt(expire[2:], 10, 64)
if err != nil {
return 0, err
}
if txHeight <= 0 {
fmt.Printf("txHeight should be grate to 0")
return 0, errors.New("txHeight should be grate to 0")
}
return txHeight + types.TxHeightFlag, nil
}
types.TxHeightFlag
是常量 1<<62
,但是当 expire
为 H:9223372036854775806
时会造成溢出
To Reproduce
./chain33-cli bty transfer -a 1000 -t 1GhMZ7vpEEGLUmxcf8KRNedjpKZYFus9dJ
./chain33-cli wallet sign -d "tx" -a 1CbEVT9RnM5oZhWMj4fxUrJX94VtRotzvs // should throw here
./chain33-cli wallet send -d "signed_tx"
Expected behavior
这个 bug 看上去似乎没有什么危害,但是它通过了 sign 阶段的检查,在 sendTransaction 阶段抛出异常,正确应该是在 sign 阶段抛出异常
Screenshots
背景
目前 写执行器的时候,需要手工构造交易,这个引起代码非常底层和冗长。
解决方案调研
1. eos table 的概念
2. 现有系统主要的代码冗余点
3. 提供什么样的封装比较合适
4. 现有行业中主要的解决方案有什么
错误的是 TypeZayedcoin --->ZEC ,
正确的应该是TypeZcash-->ZEC
1.the key store format int the Store DB is like this "mavl-coins-bty-exec-exec_addr-addr"
,eg:mavl-coins-bty-exec-16htvcBNSEA7fZhAdLJphDwQRQJaHpyHTp:1JmFaA6unrCFYEWPGRi7uuXY1KthTJxJEP
,
16htvcBNSEA7fZhAdLJphDwQRQJaHpyHTp
is the exec address,1JmFaA6unrCFYEWPGRi7uuXY1KthTJxJEP
is the specific address.
2.we can use command as following to query the result:
cli stat exec_balance -symbol bty -exec coins -addr 1JmFaA6unrCFYEWPGRi7uuXY1KthTJxJEP -exec_addr 16htvcBNSEA7fZhAdLJphDwQRQJaHpyHTp -height -1
the result is like this:
{
"totalAmount":10,
"frozenAmount":3,
"activeAmount":7,
"execBalances":[
{
"execAddr":"xxxx",
"frozen":1,
"active":2
},
...
]
}
I build the code from the master branch, and change the .toml file, just singleMode=true
to singleMode=false
, and add seeds' IPs in p2p configuration.
I lauched 5 nodes, and use rpc request IsSync
to detect, but seems cannot sync? How should I change the .toml file or the bugs in code?
工具程序tools可以考虑加入创建简单的工程创建向导功能, 内含简单的设置、查询值的合约。类似于一键创建bityuan的项目。
{
"isOK": false,
"msg": "ErrSeedWordNum"
}
{
"isOK": false,
"msg": "ErrSaveSeedFirst"
}
ErrWalletIsLocked
ErrWalletIsLocked
ErrAccountNotExist
Describe the bug
我在阅读源码中的 api 时,注意到 set_fee 可以用来设置交易费用,于是我准备测试是否会有相关的溢出,结果在我设置费用为一个大数之后,再调用 SendToAddress 时,竟然执行了一百多次 procExecAddBlock 函数,并且区块高度增加了一百多(之后每次增加的不一样,但是都很多),其中都是无效交易。
To Reproduce*
首先设置交易费用
./chain33-cli wallet set_fee -a 92233720368
然后执行下面脚本调用 SendToAddress
sendTrans = "{\"method\": \"Chain33.SendToAddress\",\"params\": [{\"From\": \"1CbEVT9RnM5oZhWMj4fxUrJX94VtRotzvs\",\"To\": \"1GhMZ7vpEEGLUmxcf8KRNedjpKZYFus9dJ\",\"amount\": 100000000}],\"id\": 0}"
print sendTrans
req2 = requests.post("http://localhost:8801",data=sendTrans)
p2p的版本在不主动配置的时候,默认最小版本与当前版本持平,最大版本是最小版本+1
chain33/executor/allow.go:isAllowLocalKey中的实现中
execer = types.GetRealExecName(execer)
当调用user.wasm.xxx合约时,通过上述调用获取到的execer为wasm,
这样就会存在用户自定义合约跨合约操作的风险,
这样的情况也会发生在user.evm.xxx的合约执行过程中。
@vipwzw 你认为呢?
Is your feature request related to a problem? Please describe.
此接口可以获取到区块中的所有交易的详情,但是详情中缺少了交易hash,在做浏览器时,需要额外的接口查找交易hash
Describe the solution you'd like
出参中增加交易的hash:
{
"id":int32,
"result":
{
"items":
[
{
"block":
{
"version":int64,
"parentHash":"string",
"txHash":"string",
"stateHash":"string",
"height":int64,
"blockTime":int64,
"txs":
[
{
"txhash": "交易的hash",
"execer":"string",
"payload":"string",
"fee":int64,
"expire":int32,
"nonce":int32,
"to":"string",
"signature":{"ty":int32,"pubkey":"string","signature":"string"}
}
]
},
"receipts":
[
{
"ty":int32,
"logs":[{"ty":int32,"log":"string"}]
}
]
}
]
}
}
Describe alternatives you've considered
如果不增加,需要先请求 chain33.getBlockOverview,获取到此区块中的交易hash,然后chain33.GetTxByHashes 获取到交易详情
Javascript VM 相对比较成熟,可以考虑确定性改造过的JavaScript VM 以避免分叉
Describe the bug
When I review the code, I found that the code like follow will dump the password in plain text.
func (store *Store) VerifyPasswordHash(password string) bool {
var WalletPwHash types.WalletPwHash
pwhashbytes, err := store.Get(CalcPasswordHash())
if pwhashbytes == nil || err != nil {
return false
}
err = json.Unmarshal(pwhashbytes, &WalletPwHash)
if err != nil {
storelog.Error("VerifyPasswordHash unmarshal", "err", err)
return false
}
pwhashstr := fmt.Sprintf("%s:%s", password, WalletPwHash.Randstr) // dump the password
pwhash := sha256.Sum256([]byte(pwhashstr))
Pwhash := pwhash[:]
//通过新的密码计算pwhash最对比
return bytes.Equal(WalletPwHash.GetPwHash(), Pwhash)
}
Expected behavior
This bug appeared in Twitter before.
https://techcrunch.com/2018/05/03/twitter-password-bug/
Screenshots
我是通过Chain33.CreateRawTransaction 这个RPC 接口构造一笔往平行链某个地址打币的交易,签名后,查询交易详情,显示 交易不成功。
下面是我构造的过程,tokenSymbol=TEST,execName=user.p.sto.token
var params = make(map[string]interface{})
params["to"] = txinfo.GetTo()
params["amount"] = int64((txinfo.GetAmount() + 0.0000001) * 1e8)
params["fee"] = 1e5
params["note"] = txinfo.GetNote()
params["isToken"] = true
params["tokenSymbol"] = txinfo.GetTokensymbol()
params["execName"] = BtyCfg.TokenExecer
parmbs, err := json.Marshal(params)
if err != nil {
return "", err
}
postdata := fmt.Sprintf({"jsonrpc":"2.0","id":2,"method":"Chain33.CreateRawTransaction","params":[%v]}
, string(parmbs))
Describe the bug
当我阅读关于merkle tree 生成的相关代码时,经过调试,我发现在交易数为单数时,会将最后一份交易copy 一份来计算 merkle tree 的 merkleRoot,如果恶意节点接收到 [tx1,tx2,tx3] 的 block,并将 [tx1,tx2,tx3,tx3] 的交易广播出去,两者的 merkleRoot 相同,可能造成造成双花攻击。
To Reproduce
在 merkle.go 的 Computation 函数中,这段代码,交易数为单数时会将最后一个交易copy 一份来计算 hash
for count != (1 << level) {
if (flage&2) != 0 && matchh {
branch = append(branch, h)
}
h = GetHashFromTwoHash(h, h) // Use two identical transactions to calculate the hash
count += (1 << level)
level++
Expected behavior
单数交易取本身哈希在merkle tree上一层计算哈希值
目前github上面的mavl裁剪中没有加入上次说的类似于多级裁剪机制,在gitlab上面的有,我是不是将gitlab上面的同步到github上先。
//二级裁剪高度,达到此高度未裁剪则放入该处
secondLevelPruningHeight = 1000000
//三级裁剪高度,达到此高度还没有裁剪,则不进行裁剪
threeLevelPruningHeight = 1500000
onceScanCount = 100000
@vipwzw
用钱包打币,需要输入很长的地址,这些地址通常比较复杂,难以记忆,如果可以通过类似DNS域名的方式来隐藏地址,这样就可以很方便的进行交易发送,构建等。
如果不删除wallet节点,只删除datadir,重新同步数据,每同步一次就会生成一个node award账户,操作多次后就会有一堆node award账户;
按照正常理解,账户应该是存在钱包中,如果钱包已经有了,应该只同步区块数据,不应该再生成新的node award地址
平行链安全的切换主节点:
不同的主节点,有不同的seq id。分成两种情况讨论:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.