Skip to content

Commit

Permalink
Merge pull request #245 from binance-chain/develop
Browse files Browse the repository at this point in the history
smart chain features
  • Loading branch information
fletcher142 authored Aug 22, 2020
2 parents 70b4386 + 992ada9 commit eedaa72
Show file tree
Hide file tree
Showing 239 changed files with 19,051 additions and 2,399 deletions.
19 changes: 11 additions & 8 deletions baseapp/baseapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res
}
querier := app.queryRouter.Route(path[1])
if querier == nil {
return sdk.ErrUnknownRequest("no custom querier found for route "+ path[1]).QueryResult()
return sdk.ErrUnknownRequest("no custom querier found for route " + path[1]).QueryResult()
}

ctx := sdk.NewContext(app.cms.CacheMultiStore(), app.CheckState.Ctx.BlockHeader(), sdk.RunTxModeCheck, app.Logger)
Expand Down Expand Up @@ -589,7 +589,7 @@ func (app *BaseApp) CheckTx(req abci.RequestCheckTx) (res abci.ResponseCheckTx)
Code: uint32(result.Code),
Data: result.Data,
Log: result.Log,
Events: result.Tags.ToEvents(),
Events: result.GetEvents(),
}
}

Expand Down Expand Up @@ -617,7 +617,7 @@ func (app *BaseApp) PreCheckTx(req abci.RequestCheckTx) (res abci.ResponseCheckT
Code: uint32(result.Code),
Data: result.Data,
Log: result.Log,
Events: result.Tags.ToEvents(),
Events: result.GetEvents(),
}
}

Expand All @@ -644,7 +644,7 @@ func (app *BaseApp) ReCheckTx(req abci.RequestCheckTx) (res abci.ResponseCheckTx
Code: uint32(result.Code),
Data: result.Data,
Log: result.Log,
Events: result.Tags.ToEvents(),
Events: result.GetEvents(),
}
}

Expand Down Expand Up @@ -679,7 +679,7 @@ func (app *BaseApp) DeliverTx(req abci.RequestDeliverTx) (res abci.ResponseDeliv
Code: uint32(result.Code),
Data: result.Data,
Log: result.Log,
Events: result.Tags.ToEvents(),
Events: result.GetEvents(),
}
}

Expand All @@ -691,7 +691,7 @@ func (app *BaseApp) PreDeliverTx(req abci.RequestDeliverTx) (res abci.ResponseDe
Code: uint32(result.Code),
Data: result.Data,
Log: result.Log,
Events: result.Tags.ToEvents(),
Events: result.GetEvents(),
}
}

Expand Down Expand Up @@ -747,6 +747,7 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode sdk.RunTxMode)
logs := make([]string, 0, len(msgs))
var data []byte // NOTE: we just append them all (?!)
var tags sdk.Tags // also just append them all
var events sdk.Events
var code sdk.ABCICodeType
for msgIdx, msg := range msgs {
// Match route.
Expand All @@ -762,6 +763,7 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode sdk.RunTxMode)
// Append Data and Tags
data = append(data, msgResult.Data...)
tags = append(tags, msgResult.Tags...)
events = append(events, msgResult.Events...)

// Stop execution and return on first failed message.
if !msgResult.IsOK() {
Expand All @@ -771,7 +773,7 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode sdk.RunTxMode)
}

// Construct usable logs in multi-message transactions.
logs = append(logs, "Msg " + strconv.Itoa(msgIdx) + ": " + msgResult.Log)
logs = append(logs, "Msg "+strconv.Itoa(msgIdx)+": "+msgResult.Log)
}
// A tx must only contain one msg. If the msg execution is success, record it
if code == sdk.ABCICodeOK {
Expand All @@ -783,7 +785,8 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode sdk.RunTxMode)
Data: data,
Log: strings.Join(logs, "\n"),
// TODO: FeeAmount/FeeDenom
Tags: tags,
Tags: tags,
Events: events,
}

return result
Expand Down
42 changes: 42 additions & 0 deletions bsc/bloom9.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package bsc

import (
"fmt"
"math/big"
)

const (
// BloomByteLength represents the number of bytes used in a header log bloom.
BloomByteLength = 256
)

// Bloom represents a 2048 bit bloom filter.
type Bloom [BloomByteLength]byte

// SetBytes sets the content of b to the given bytes.
// It panics if d is not of suitable size.
func (b *Bloom) SetBytes(d []byte) {
if len(b) < len(d) {
panic(fmt.Sprintf("bloom bytes too big %d %d", len(b), len(d)))
}
copy(b[BloomByteLength-len(d):], d)
}

// Big converts b to a big integer.
func (b Bloom) Big() *big.Int {
return new(big.Int).SetBytes(b[:])
}

func (b Bloom) Bytes() []byte {
return b[:]
}

// MarshalText encodes b as a hex string with 0x prefix.
func (b Bloom) MarshalText() ([]byte, error) {
return Bytes(b[:]).MarshalText()
}

// UnmarshalText b as a hex string with 0x prefix.
func (b *Bloom) UnmarshalText(input []byte) error {
return UnmarshalFixedText("Bloom", input, b[:])
}
216 changes: 216 additions & 0 deletions bsc/header.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
package bsc

import (
"encoding/json"
"errors"
"io"
"math/big"

"github.com/tendermint/tendermint/crypto/secp256k1"
"golang.org/x/crypto/sha3"

"github.com/cosmos/cosmos-sdk/bsc/rlp"
)

type Header struct {
ParentHash Hash `json:"parentHash" gencodec:"required"`
UncleHash Hash `json:"sha3Uncles" gencodec:"required"`
Coinbase Address `json:"miner" gencodec:"required"`
Root Hash `json:"stateRoot" gencodec:"required"`
TxHash Hash `json:"transactionsRoot" gencodec:"required"`
ReceiptHash Hash `json:"receiptsRoot" gencodec:"required"`
Bloom Bloom `json:"logsBloom" gencodec:"required"`
Difficulty int64 `json:"difficulty" gencodec:"required"`
Number int64 `json:"number" gencodec:"required"`
GasLimit uint64 `json:"gasLimit" gencodec:"required"`
GasUsed uint64 `json:"gasUsed" gencodec:"required"`
Time uint64 `json:"timestamp" gencodec:"required"`
Extra []byte `json:"extraData" gencodec:"required"`
MixDigest Hash `json:"mixHash"`
Nonce BlockNonce `json:"nonce"`
}

// MarshalJSON marshals as JSON.
func (h Header) MarshalJSON() ([]byte, error) {
type Header struct {
ParentHash Hash `json:"parentHash" gencodec:"required"`
UncleHash Hash `json:"sha3Uncles" gencodec:"required"`
Coinbase Address `json:"miner" gencodec:"required"`
Root Hash `json:"stateRoot" gencodec:"required"`
TxHash Hash `json:"transactionsRoot" gencodec:"required"`
ReceiptHash Hash `json:"receiptsRoot" gencodec:"required"`
Bloom Bloom `json:"logsBloom" gencodec:"required"`
Difficulty *Big `json:"difficulty" gencodec:"required"`
Number *Big `json:"number" gencodec:"required"`
GasLimit Uint64 `json:"gasLimit" gencodec:"required"`
GasUsed Uint64 `json:"gasUsed" gencodec:"required"`
Time Uint64 `json:"timestamp" gencodec:"required"`
Extra Bytes `json:"extraData" gencodec:"required"`
MixDigest Hash `json:"mixHash"`
Nonce BlockNonce `json:"nonce"`
}
var enc Header
enc.ParentHash = h.ParentHash
enc.UncleHash = h.UncleHash
enc.Coinbase = h.Coinbase
enc.Root = h.Root
enc.TxHash = h.TxHash
enc.ReceiptHash = h.ReceiptHash
enc.Bloom = h.Bloom
enc.Difficulty = (*Big)(big.NewInt(h.Difficulty))
enc.Number = (*Big)(big.NewInt(h.Number))
enc.GasLimit = Uint64(h.GasLimit)
enc.GasUsed = Uint64(h.GasUsed)
enc.Time = Uint64(h.Time)
enc.Extra = h.Extra
enc.MixDigest = h.MixDigest
enc.Nonce = h.Nonce
return json.Marshal(&enc)
}

// UnmarshalJSON unmarshals from JSON.
func (h *Header) UnmarshalJSON(input []byte) error {
type Header struct {
ParentHash *Hash `json:"parentHash" gencodec:"required"`
UncleHash *Hash `json:"sha3Uncles" gencodec:"required"`
Coinbase *Address `json:"miner" gencodec:"required"`
Root *Hash `json:"stateRoot" gencodec:"required"`
TxHash *Hash `json:"transactionsRoot" gencodec:"required"`
ReceiptHash *Hash `json:"receiptsRoot" gencodec:"required"`
Bloom *Bloom `json:"logsBloom" gencodec:"required"`
Difficulty *Big `json:"difficulty" gencodec:"required"`
Number *Big `json:"number" gencodec:"required"`
GasLimit *Uint64 `json:"gasLimit" gencodec:"required"`
GasUsed *Uint64 `json:"gasUsed" gencodec:"required"`
Time *Uint64 `json:"timestamp" gencodec:"required"`
Extra *Bytes `json:"extraData" gencodec:"required"`
MixDigest *Hash `json:"mixHash"`
Nonce *BlockNonce `json:"nonce"`
}
var dec Header
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.ParentHash == nil {
return errors.New("missing required field 'parentHash' for Header")
}
h.ParentHash = *dec.ParentHash
if dec.UncleHash == nil {
return errors.New("missing required field 'sha3Uncles' for Header")
}
h.UncleHash = *dec.UncleHash
if dec.Coinbase == nil {
return errors.New("missing required field 'miner' for Header")
}
h.Coinbase = *dec.Coinbase
if dec.Root == nil {
return errors.New("missing required field 'stateRoot' for Header")
}
h.Root = *dec.Root
if dec.TxHash == nil {
return errors.New("missing required field 'transactionsRoot' for Header")
}
h.TxHash = *dec.TxHash
if dec.ReceiptHash == nil {
return errors.New("missing required field 'receiptsRoot' for Header")
}
h.ReceiptHash = *dec.ReceiptHash
if dec.Bloom == nil {
return errors.New("missing required field 'logsBloom' for Header")
}
h.Bloom = *dec.Bloom
if dec.Difficulty == nil {
return errors.New("missing required field 'difficulty' for Header")
}
h.Difficulty = dec.Difficulty.ToInt().Int64()
if dec.Number == nil {
return errors.New("missing required field 'number' for Header")
}
h.Number = dec.Number.ToInt().Int64()
if dec.GasLimit == nil {
return errors.New("missing required field 'gasLimit' for Header")
}
h.GasLimit = uint64(*dec.GasLimit)
if dec.GasUsed == nil {
return errors.New("missing required field 'gasUsed' for Header")
}
h.GasUsed = uint64(*dec.GasUsed)
if dec.Time == nil {
return errors.New("missing required field 'timestamp' for Header")
}
h.Time = uint64(*dec.Time)
if dec.Extra == nil {
return errors.New("missing required field 'extraData' for Header")
}
h.Extra = *dec.Extra
if dec.MixDigest != nil {
h.MixDigest = *dec.MixDigest
}
if dec.Nonce != nil {
h.Nonce = *dec.Nonce
}
return nil
}

const extraSeal = 65

func (h *Header) GetSignature() ([]byte, error) {
if len(h.Extra) < extraSeal {
return nil, errors.New("extra-data 65 byte signature suffix missing")
}
signature := h.Extra[len(h.Extra)-extraSeal:]
return signature, nil
}

func (h *Header) ExtractSignerFromHeader() (signer Address, err error) {
signature, err := h.GetSignature()
if err != nil {
return
}
pubKey, err := secp256k1.RecoverPubkey(SealHash(h).Bytes(), signature)
if err != nil {
return
}
copy(signer[:], Keccak256(pubKey[1:])[12:])
return
}

// Keccak256 calculates and returns the Keccak256 hash of the input data.
func Keccak256(data ...[]byte) []byte {
d := sha3.NewLegacyKeccak256()
for _, b := range data {
d.Write(b)
}
return d.Sum(nil)
}

// SealHash returns the hash of a block prior to it being sealed.
func SealHash(header *Header) (hash Hash) {
hasher := sha3.NewLegacyKeccak256()
encodeSigHeader(hasher, header)
hasher.Sum(hash[:0])
return hash
}

func encodeSigHeader(w io.Writer, header *Header) {
err := rlp.Encode(w, []interface{}{
header.ParentHash,
header.UncleHash,
header.Coinbase,
header.Root,
header.TxHash,
header.ReceiptHash,
header.Bloom,
big.NewInt(header.Difficulty),
big.NewInt(header.Number),
header.GasLimit,
header.GasUsed,
header.Time,
header.Extra[:len(header.Extra)-65], // this will panic if extra is too short, should check before calling encodeSigHeader
header.MixDigest,
header.Nonce,
})
if err != nil {
panic("can't encode: " + err.Error())
}
}
41 changes: 41 additions & 0 deletions bsc/header_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package bsc

import (
"encoding/hex"
"testing"

"github.com/stretchr/testify/require"
)

func TestHeader_UnmarshalJSON(t *testing.T) {
h := &Header{}
jsonStr := `{"difficulty":"0x2",
"extraData":"0xd98301090a846765746889676f312e31322e3137856c696e75780000000000005b28385ac3a02a84c391c5d90b3aa0a62365136d80892c5e6158797b394f436c70c697f8d44d6dcfa49d4871897d2ff132356496f066d0adf28ddb3b7099ff5d00",
"gasLimit":"0x2625a00",
"gasUsed":"0xd752e8",
"hash":"0x14c62182b7138b45c400afccbebda3c68a78ca7a6100d3e1fe9e1e8e71ef2b66",
"logsBloom":"0x984e3983604a6120412617213b05004281984c60680c0cd0070200181d240016810500880001002b00055a0470461c09201145010c4e0729408998810a8800400a280247010848590804014800800454317020c88041a40248321010229290e68000011a808068002a56e2c41087114422a9841921a24ea709000430069010315e2c120124080610200cc18c137a0021206170070de90887502148600090002a50440040800905028a640401210c004089c20c4000e44054100cd00907642b4040900a920126454158b64181002d10014e80820508201c0480492880008c84102b0614804474840400413818940819042084c0042a002040498000c201309400",
"miner":"0xfffffffffffffffffffffffffffffffffffffffe",
"mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce":"0x0000000000000000",
"number":"0x1b4",
"parentHash":"0xbfbb0f930378e623c27c1b6888694abd63926581697cf70a268a7455497e1011",
"receiptsRoot":"0x32a9e85c5b51c5b99ce76dac6d1a75dd603bd7406b36d62cf8e74475c2be7462",
"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"size":"0xd73c",
"stateRoot":"0xa20ff6190c7d8a7993a50a3d60bdeca460c19128ba363413f5bff57670ddccb1",
"timestamp":"0x5e79a878",
"totalDifficulty":"0x365",
"transactionsRoot":"0x8f192c648a6d9035adbf72a55cab5652e3c0d7549c378be45bd3d5248d4b3ac5"
}`
err := h.UnmarshalJSON([]byte(jsonStr))
require.NoError(t, err)

signature, err := h.GetSignature()
require.NoError(t, err)
require.Equal(t, "5b28385ac3a02a84c391c5d90b3aa0a62365136d80892c5e6158797b394f436c70c697f8d44d6dcfa49d4871897d2ff132356496f066d0adf28ddb3b7099ff5d00", hex.EncodeToString(signature))

signer, err := h.ExtractSignerFromHeader()
require.NoError(t, err)
require.Equal(t, "0xB12fA6F899a16C156B67dBcb124d3733E72A164E", signer.String())
}
Loading

0 comments on commit eedaa72

Please sign in to comment.