Skip to content

Web3q bihs #25

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: w3q_tmp
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,5 @@ profile.cov
/dashboard/assets/package-lock.json

**/yarn-error.log
node*
geth
28 changes: 28 additions & 0 deletions bihs_genesis.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"config": {
"chainId": 121,
"homesteadBlock": 0,
"eip150Block": 0,
"eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"istanbulBlock": 0,
"bihs": {
"period": 3
}
},
"nonce": "0x0",
"timestamp": "0x605c499c",
"extraData": "0x00000000000000000000000000000000000000000000000000000000000000007d84d07aca491a6ccbb1577eccbc5e18cb7de0880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x47b760",
"difficulty": "0x1",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": {},
"number": "0x0",
"gasUsed": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
58 changes: 58 additions & 0 deletions consensus/bihs/adapter/block.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package adapter

import (
"fmt"

"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ontio/ontology/common"
"github.com/zhiqiangxu/bihs"
)

type Block types.Block

func DefaultBlock() bihs.Block {
return &Block{}
}

func (b *Block) TimeMil() uint64 {
return (*types.Block)(b).Header().Time * 1000
}

func (b *Block) Height() uint64 {
return (*types.Block)(b).Header().Number.Uint64()
}

func (b *Block) Hash() bihs.Hash {
hash := (*types.Block)(b).Header().Hash()
return hash[:]
}

func (b *Block) Empty() bool {
return len((*types.Block)(b).Transactions()) == 0
}

func (b *Block) Serialize(sink *common.ZeroCopySink) {
// (*types.Block)(b).EncodeRLP()
bytes, err := rlp.EncodeToBytes((*types.Block)(b))
if err != nil {
panic(fmt.Sprintf("rlp.EncodeToBytes failed:%v", err))
}
sink.WriteVarBytes(bytes)
}

func (b *Block) Deserialize(source *common.ZeroCopySource) error {
bytes, err := source.ReadVarBytes()
if err != nil {
return fmt.Errorf("Block.Deserialize source.ReadVarBytes failed:%v", err)
}
return rlp.DecodeBytes(bytes, (*types.Block)(b))
}

func (b *Block) header() *types.Header {
return (*types.Block)(b).Header()
}

func (b *Block) withSeal(header *types.Header) *types.Block {
return (*types.Block)(b).WithSeal(header)
}
42 changes: 42 additions & 0 deletions consensus/bihs/adapter/logger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package adapter

import (
"fmt"

"github.com/ethereum/go-ethereum/log"
)

type Logger struct {
}

func (l *Logger) Info(a ...interface{}) {
log.Info("bihs", a...)
}

func (l *Logger) Infof(format string, a ...interface{}) {
log.Info(fmt.Sprintf(format, a...))
}

func (l *Logger) Debug(a ...interface{}) {
log.Debug("bihs", a...)
}

func (l *Logger) Debugf(format string, a ...interface{}) {
log.Debug(fmt.Sprintf(format, a...))
}

func (l *Logger) Fatal(a ...interface{}) {
log.Crit("bihs", a...)
}

func (l *Logger) Fatalf(format string, a ...interface{}) {
log.Crit(fmt.Sprintf(format, a...))
}

func (l *Logger) Error(a ...interface{}) {
log.Warn("bihs", a...)
}

func (l *Logger) Errorf(format string, a ...interface{}) {
l.Error(fmt.Sprintf(format, a...))
}
86 changes: 86 additions & 0 deletions consensus/bihs/adapter/p2p.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package adapter

import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/bihs/gov"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p"
ocommon "github.com/ontio/ontology/common"
"github.com/zhiqiangxu/bihs"
)

type P2P struct {
bc Broadcaster
chain *core.BlockChain
gov *gov.Governance
ch chan *bihs.Msg
}

type Broadcaster interface {
Unicast(target common.Address, msgcode uint64, data interface{})
Multicast(targets []common.Address, msgcode uint64, data interface{})
}

const chanSize = 20

func NewP2P(bc Broadcaster, chain *core.BlockChain, gov *gov.Governance) *P2P {
return &P2P{bc: bc, chain: chain, gov: gov, ch: make(chan *bihs.Msg, chanSize)}
}

func (p *P2P) Broadcast(msg *bihs.Msg) {

sink := ocommon.NewZeroCopySink(nil)
msg.Serialize(sink)
payload := sink.Bytes()
validators := p.gov.ValidatorP2PAddrs(msg.Height)
log.Info("Broadcast", "#payload", len(payload), "type", msg.Type, "height", msg.Height, "view", msg.View, "msg hash", msg.Hash())
p.bc.Multicast(validators, ConsensusMsgCode, payload)

// {
// var decodeMsg bihs.Msg
// err := decodeMsg.Deserialize(ocommon.NewZeroCopySource(payload))
// if err != nil {
// panic(fmt.Sprintf("decodeMsg.Deserialize failed:%v", err))
// }
// }
}

var ConsensusMsgCode uint64

func (p *P2P) Send(id bihs.ID, msg *bihs.Msg) {
target := p.gov.ValidatorP2PAddr(common.BytesToAddress(id))
sink := ocommon.NewZeroCopySink(nil)
msg.Serialize(sink)
payload := sink.Bytes()
p.bc.Unicast(target, ConsensusMsgCode, payload)
}

func (p *P2P) MsgCh() <-chan *bihs.Msg {
return p.ch
}

func (p *P2P) HandleP2pMsg(msg p2p.Msg) (err error) {

var payload []byte
if err = msg.Decode(&payload); err != nil {
return
}

var bihsMsg bihs.Msg
if err = bihsMsg.Deserialize(ocommon.NewZeroCopySource(payload)); err != nil {
log.Info("bihs.Msg", "#payload", len(payload), "type", bihsMsg.Type, "height", bihsMsg.Height, "view", bihsMsg.View, "qc", bihsMsg.Justify)
return
}

log.Info("HandleP2pMsg", "#payload", len(payload), "msg hash", bihsMsg.Hash())

select {
case p.ch <- &bihsMsg:
default:
log.Warn("p2p msg dropped because channel is ful")
}

// TODO help propagation?
return nil
}
53 changes: 53 additions & 0 deletions consensus/bihs/adapter/p2p_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package adapter

import (
"encoding/hex"
"encoding/json"
"testing"

ocommon "github.com/ontio/ontology/common"
"github.com/zhiqiangxu/bihs"
)

func TestEncoding(t *testing.T) {
// init
{
bihs.DefaultBlockFunc = DefaultBlock
}

{
var bihsMsg bihs.Msg
bytes, err := hex.DecodeString("0102000000000000000100000000000000000101fd1402f90211f9020ca0b6a7e35ed580a6cb6d236a834ee588f68da29de44ad62ff250090dded3002d86a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001018347b7608084605c499d98d783010a10846765746886676f312e31378664617277696ea0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff880000000000000000c0c00041ed584c2c3a6a2098410e956025c40ed8d378fd3486d32075c7b9b68a795a7ab35107076a56b93d193c8a37289b83b08f256c976133ac28dbe41474a9cfb8884300")
if err != nil {
t.Fatal("hex.DecodeString failed", err)
}
err = bihsMsg.Deserialize(ocommon.NewZeroCopySource(bytes))
if err != nil {
t.Fatal("bihsMsg.Deserialize failed", err)
}
}

{
var bihsMsg bihs.Msg
jsonBytes, err := hex.DecodeString("7b2254797065223a332c22486569676874223a312c2256696577223a312c224a757374696679223a7b2254797065223a322c22486569676874223a312c2256696577223a312c22426c6f636b48617368223a224533676264344f4b48507942776c436363484639724771704c7a594b3436444a586a4a614c43566c754a673d222c2253696773223a226439325a75335236376637345334317165537463652b6f5a66364a7155756d646964576748356c617961344177474f64496453497154666c71387a5443417679702f657932307a6c736c3148757655356c33536b785144556130536c4a4d3961757a37687972594e55726e6c594a6b6466772f39414a745348796d476330636d37794d6851774a42456d4a366b6330476648692f6e445a347449796d6e6b306f6d7343437975634f6a2f6a7041413d3d222c224269746d6170223a6e756c6c7d2c224e6f6465223a6e756c6c2c224944223a6e756c6c2c225061727469616c536967223a225465717149386f766f61544e4950444f6f536b6b4f48774d39467a41634753496e5753524745437a353270333533532f664262394368635978502f51644f596e476d3268564f6e682b74316f7068656a394d57456951453d227d")
if err != nil {
t.Fatal("hex.DecodeString failed", err)
}
bihsMsg.Node = &bihs.BlockOrHash{}
bihsMsg.Node.Blk = DefaultBlock()
err = json.Unmarshal(jsonBytes, &bihsMsg)
if err != nil {
t.Fatal("json.Unmarshal failed", err)
}

sink := ocommon.NewZeroCopySink(nil)
bihsMsg.Serialize(sink)
payload := sink.Bytes()

var decodedMsg bihs.Msg
if err = decodedMsg.Deserialize(ocommon.NewZeroCopySource(payload)); err != nil {
t.Fatal("decodedMsg.Deserialize failed", err)
}
}

}
95 changes: 95 additions & 0 deletions consensus/bihs/adapter/signer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package adapter

import (
"crypto/ecdsa"
"fmt"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
"github.com/zhiqiangxu/bihs"
)

type Signer struct {
address common.Address
privateKey *ecdsa.PrivateKey
}

func NewSigner(privateKey *ecdsa.PrivateKey) *Signer {
address := crypto.PubkeyToAddress(privateKey.PublicKey)
return &Signer{
address: address,
privateKey: privateKey,
}
}

func (s *Signer) Address() common.Address {
return s.address
}

func (s *Signer) Sign(data []byte) (sig []byte) {
hashData := crypto.Keccak256(data)
sig, err := crypto.Sign(hashData, s.privateKey)
if err != nil {
panic(fmt.Sprintf("crypto.Sign failed:%v", err))
}

return
}

func (s *Signer) Verify(data []byte, sig []byte) (id bihs.ID, err error) {
hashData := crypto.Keccak256(data)
pubkey, err := crypto.Ecrecover(hashData, sig)
if err != nil {
return
}

var signer common.Address
copy(signer[:], crypto.Keccak256(pubkey[1:])[12:])
id = signer[:]
return
}

func (s *Signer) TCombine(_ []byte, sigs [][]byte) []byte {
var aggregatedSigs []byte
for _, sig := range sigs {
aggregatedSigs = append(aggregatedSigs, sig...)
}
return aggregatedSigs
}

func (s *Signer) TVerify(data []byte, sigs []byte, ids []bihs.ID, quorum int32) bool {
log.Info("TVerify", "#sigs", len(sigs), "ids", ids, "quorum", quorum)
if len(sigs)%crypto.SignatureLength != 0 {
return false
}

addrMap := make(map[common.Address]bool)
for _, id := range ids {
addr := common.BytesToAddress(id)
if addrMap[addr] {
log.Info("false for dup ids")
return false
}
addrMap[addr] = true
}
sigCount := int32(0)
for len(sigs) >= crypto.SignatureLength {
signer, err := s.Verify(data, sigs[0:crypto.SignatureLength])
if err != nil {
log.Info("false for verify error", "err", err)
return false
}
addr := common.BytesToAddress(signer)
if !addrMap[addr] {
log.Info("false for invalid signer", "addr", addr)
return false
}
delete(addrMap, addr)
sigCount++
sigs = sigs[crypto.SignatureLength:]
}

log.Info("TVerify", "sigCount", sigCount, "quorum", quorum)
return sigCount >= quorum
}
Loading