Compare commits

...

21 Commits

Author SHA1 Message Date
zjubfd
f4816ee8b7 add chain id into sign bytes to avoid replay attack (#18) 2020-07-09 15:46:37 +08:00
yutianwu
8d48b0deb8 Merge pull request #17 from binance-chain/develop
[R4R] Prepare for release v1.0.0-beta.0
2020-07-03 17:59:01 +08:00
fudongbai
1940dc887c add changelog for v1.0.0-beta.0 2020-07-03 17:56:34 +08:00
fudongbai
2f2778deec update metaversion to beta.0 2020-07-03 16:07:04 +08:00
zjubfd
6f46fc0589 allow slash failed (#15) 2020-06-30 20:22:57 +08:00
HaoyangLiu
6f40b0e238 Merge pull request #14 from binance-chain/crossContract
[R4R]add cross chain contract to system contract
2020-06-30 16:39:53 +08:00
fudongbai
ef1e8746d6 add cross chain contract to system contract 2020-06-30 08:38:15 +00:00
zjubfd
511bbf546f add bep2p tokens for faucet (#5) 2020-06-30 16:16:26 +08:00
zjubfd
5e4f5785c7 fix debug_traceTransaction crashed issue (#13) 2020-06-30 16:15:12 +08:00
zjubfd
11bc803884 Merge pull request #11 from guagualvcha/gas_limit
[R4R]remove redundant gaslimit check
2020-06-24 16:22:21 +08:00
fudongbai
6a19c9803c remove redundant gaslimit check 2020-06-24 16:17:22 +08:00
yutianwu
9f1aaecb29 Merge pull request #10 from guagualvcha/gas_limit
[R4R]add gas limit check in parlia implement
2020-06-18 10:19:27 +08:00
fudongbai
4bd4469151 add gas limit check in parlia implement 2020-06-18 00:26:27 +08:00
zjubfd
ce14f2cae5 Merge pull request #6 from guagualvcha/stale_depth
[R4R] modify params for Parlia consensus with 21 validators
2020-06-17 12:10:21 +08:00
fudongbai
2ff7a21d64 update stale depth 2020-06-15 17:31:40 +08:00
zjubfd
e83397e26a Merge pull request #4 from binance-chain/issue3
[R4R]fix validator failed to sync a block produced by itself,  resolve #3
2020-06-15 17:16:35 +08:00
fudongbai
ed9b28fe7b fix validator failed to sync a block produced by itself 2020-06-02 16:41:48 +08:00
zjubfd
fd8c9c0f1f Merge pull request #1 from binance-chain/gov
[R4R]add gov/tokenHub/RelayerIncentivize contracts to the init list and apply  strict condition for system transaction
2020-06-01 15:51:58 +08:00
zjubfd
b72be127cf update 'running a node' part of readme (#2) 2020-05-25 17:41:47 +08:00
fudongbai
4909842097 add gov init transaction 2020-05-22 10:38:14 +08:00
fudongbai
39c80ce175 more strick condition for system transaction 2020-05-22 10:21:57 +08:00
14 changed files with 233 additions and 116 deletions

17
CHANGELOG.md Normal file
View File

@@ -0,0 +1,17 @@
# Changelog
## v1.0.0-beta.0
FEATURES
* [\#5](https://github.com/binance-chain/bsc/pull/5) enable bep2e tokens for faucet
* [\#14](https://github.com/binance-chain/bsc/pull/14) add cross chain contract to system contract
* [\#15](https://github.com/binance-chain/bsc/pull/15) Allow liveness slash fail
IMPROVEMENT
* [\#11](https://github.com/binance-chain/bsc/pull/11) remove redundant gaslimit check
BUGFIX
* [\#4](https://github.com/binance-chain/bsc/pull/4) fix validator failed to sync a block produced by itself
* [\#6](https://github.com/binance-chain/bsc/pull/6) modify params for Parlia consensus with 21 validators
* [\#10](https://github.com/binance-chain/bsc/pull/10) add gas limit check in parlia implement
* [\#13](https://github.com/binance-chain/bsc/pull/13) fix debug_traceTransaction crashed issue

View File

@@ -104,14 +104,14 @@ The hardware must meet certain requirements to run a full node.
Steps:
1. Download the config and genesis files. You need to have [genesis.json](https://github.com/binance-chain/smart-chain-binary/blob/pre-release/bsc/fullnode/config/genesis.json) and [config.toml](https://github.com/binance-chain/smart-chain-binary/blob/pre-release/bsc/fullnode/config/config.toml)
1. Download the binary, config and genesis files from [release](https://github.com/binance-chain/bsc/releases/download/v1.0.0-alpha.0/binary.zip), or compile the binary by `make geth`.
2. Init genesis state: `./geth --datadir node init genesis.json`.
3. Start your fullnode: `./geth --config ./config.toml --datadir ./node`.
4. Or start a validator node: `./geth --config ./config.toml --datadir ./node -unlock ${validatorAddr} --mine --allow-insecure-unlock`. The ${validatorAddr} is the wallet account address of your running validator node.
*Note: The default p2p port is 30311 and the RPC port is 8575 which is different from Ethereum.*
More details about [running a node](https://github.com/binance-chain/docs-site/blob/add-bsc/docs/smart-chain/developer/fullnode.md) and [becoming a validator](https://github.com/binance-chain/docs-site/blob/add-bsc/docs/guides/concepts/bc-staking.md).
More details about [running a node](https://docs.binance.org/smart-chain/developer/fullnode.html) and [becoming a validator](https://docs.binance.org/smart-chain/validator/candidate.html).
*Note: Although there are some internal protective measures to prevent transactions from
crossing over between the main network and test network, you should make sure to always

View File

@@ -42,6 +42,7 @@ import (
"time"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
@@ -83,11 +84,15 @@ var (
noauthFlag = flag.Bool("noauth", false, "Enables funding requests without authentication")
logFlag = flag.Int("loglevel", 3, "Log level to use for Ethereum and the faucet")
fixGasPrice = flag.Int64("faucet.fixedprice", 0, "Will use fixed gas price if specified")
bep2eContracts = flag.String("bep2eContracts", "", "the list of bep2p contracts")
bep2eSymbols = flag.String("bep2eSymbols", "", "the symbol of bep2p tokens")
bep2eAmounts = flag.String("bep2eAmounts", "", "the amount of bep2p tokens")
fixGasPrice = flag.Int64("faucet.fixedprice", 0, "Will use fixed gas price if specified")
)
var (
ether = new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)
ether = new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)
bep2eAbiJson = `[ { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "owner", "type": "address" }, { "indexed": true, "internalType": "address", "name": "spender", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" } ], "name": "Approval", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "from", "type": "address" }, { "indexed": true, "internalType": "address", "name": "to", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" } ], "name": "Transfer", "type": "event" }, { "inputs": [], "name": "totalSupply", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "decimals", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "symbol", "outputs": [ { "internalType": "string", "name": "", "type": "string" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "getOwner", "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "account", "type": "address" } ], "name": "balanceOf", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "recipient", "type": "address" }, { "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "transfer", "outputs": [ { "internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "_owner", "type": "address" }, { "internalType": "address", "name": "spender", "type": "address" } ], "name": "allowance", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "spender", "type": "address" }, { "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "approve", "outputs": [ { "internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "sender", "type": "address" }, { "internalType": "address", "name": "recipient", "type": "address" }, { "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "transferFrom", "outputs": [ { "internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "nonpayable", "type": "function" } ]`
)
var (
@@ -110,7 +115,39 @@ func main() {
amounts[i] = strings.TrimSuffix(amounts[i], "s")
}
}
bep2eNumAmounts := make([]string, 0)
if bep2eAmounts != nil && len(*bep2eAmounts) > 0 {
bep2eNumAmounts = strings.Split(*bep2eAmounts, ",")
}
symbols := make([]string, 0)
if bep2eSymbols != nil && len(*bep2eSymbols) > 0 {
symbols = strings.Split(*bep2eSymbols, ",")
}
contracts := make([]string, 0)
if bep2eContracts != nil && len(*bep2eContracts) > 0 {
contracts = strings.Split(*bep2eContracts, ",")
}
if len(bep2eNumAmounts) != len(symbols) || len(symbols) != len(contracts) {
log.Crit("Length of bep2eContracts, bep2eSymbols, bep2eAmounts mismatch")
}
bep2eInfos := make(map[string]bep2eInfo, 0)
for idx, s := range symbols {
n, ok := big.NewInt(0).SetString(bep2eNumAmounts[idx], 10)
if !ok {
log.Crit("failed to parse bep2eAmounts")
}
amountStr := big.NewFloat(0).Quo(big.NewFloat(0).SetInt(n), big.NewFloat(0).SetInt64(params.Ether)).String()
bep2eInfos[s] = bep2eInfo{
Contract: common.HexToAddress(contracts[idx]),
Amount: *n,
AmountStr: amountStr,
}
}
// Load up and render the faucet website
tmpl, err := Asset("faucet.html")
if err != nil {
@@ -118,10 +155,11 @@ func main() {
}
website := new(bytes.Buffer)
err = template.Must(template.New("").Parse(string(tmpl))).Execute(website, map[string]interface{}{
"Network": *netnameFlag,
"Amounts": amounts,
"Recaptcha": *captchaToken,
"NoAuth": *noauthFlag,
"Network": *netnameFlag,
"Amounts": amounts,
"Recaptcha": *captchaToken,
"NoAuth": *noauthFlag,
"Bep2eInfos": bep2eInfos,
})
if err != nil {
log.Crit("Failed to render the faucet template", "err", err)
@@ -162,7 +200,7 @@ func main() {
ks.Unlock(acc, pass)
// Assemble and start the faucet light service
faucet, err := newFaucet(genesis, *ethPortFlag, enodes, *netFlag, *statsFlag, ks, website.Bytes())
faucet, err := newFaucet(genesis, *ethPortFlag, enodes, *netFlag, *statsFlag, ks, website.Bytes(), bep2eInfos)
if err != nil {
log.Crit("Failed to start faucet", "err", err)
}
@@ -181,6 +219,12 @@ type request struct {
Tx *types.Transaction `json:"tx"` // Transaction funding the account
}
type bep2eInfo struct {
Contract common.Address
Amount big.Int
AmountStr string
}
// faucet represents a crypto faucet backed by an Ethereum light client.
type faucet struct {
config *params.ChainConfig // Chain configurations for signing
@@ -201,9 +245,12 @@ type faucet struct {
update chan struct{} // Channel to signal request updates
lock sync.RWMutex // Lock protecting the faucet's internals
bep2eInfos map[string]bep2eInfo
bep2eAbi abi.ABI
}
func newFaucet(genesis *core.Genesis, port int, enodes []*discv5.Node, network uint64, stats string, ks *keystore.KeyStore, index []byte) (*faucet, error) {
func newFaucet(genesis *core.Genesis, port int, enodes []*discv5.Node, network uint64, stats string, ks *keystore.KeyStore, index []byte, bep2eInfos map[string]bep2eInfo) (*faucet, error) {
// Assemble the raw devp2p protocol stack
stack, err := node.New(&node.Config{
Name: "geth",
@@ -222,6 +269,10 @@ func newFaucet(genesis *core.Genesis, port int, enodes []*discv5.Node, network u
if err != nil {
return nil, err
}
bep2eAbi, err := abi.JSON(strings.NewReader(bep2eAbiJson))
if err != nil {
return nil, err
}
// Assemble the Ethereum light client protocol
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
cfg := eth.DefaultConfig
@@ -261,14 +312,16 @@ func newFaucet(genesis *core.Genesis, port int, enodes []*discv5.Node, network u
client := ethclient.NewClient(api)
return &faucet{
config: genesis.Config,
stack: stack,
client: client,
index: index,
keystore: ks,
account: ks.Accounts()[0],
timeouts: make(map[string]time.Time),
update: make(chan struct{}, 1),
config: genesis.Config,
stack: stack,
client: client,
index: index,
keystore: ks,
account: ks.Accounts()[0],
timeouts: make(map[string]time.Time),
update: make(chan struct{}, 1),
bep2eInfos: bep2eInfos,
bep2eAbi: bep2eAbi,
}, nil
}
@@ -371,6 +424,7 @@ func (f *faucet) apiHandler(w http.ResponseWriter, r *http.Request) {
URL string `json:"url"`
Tier uint `json:"tier"`
Captcha string `json:"captcha"`
Symbol string `json:"symbol"`
}
if err = conn.ReadJSON(&msg); err != nil {
return
@@ -475,13 +529,31 @@ func (f *faucet) apiHandler(w http.ResponseWriter, r *http.Request) {
fund bool
timeout time.Time
)
if timeout = f.timeouts[username]; time.Now().After(timeout) {
// User wasn't funded recently, create the funding transaction
amount := new(big.Int).Mul(big.NewInt(int64(*payoutFlag)), ether)
amount = new(big.Int).Mul(amount, new(big.Int).Exp(big.NewInt(5), big.NewInt(int64(msg.Tier)), nil))
amount = new(big.Int).Div(amount, new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(msg.Tier)), nil))
tx := types.NewTransaction(f.nonce+uint64(len(f.reqs)), address, amount, 21000, f.price, nil)
if timeout = f.timeouts[username]; time.Now().After(timeout) {
var tx *types.Transaction
if msg.Symbol == "BNB" {
// User wasn't funded recently, create the funding transaction
amount := new(big.Int).Mul(big.NewInt(int64(*payoutFlag)), ether)
amount = new(big.Int).Mul(amount, new(big.Int).Exp(big.NewInt(5), big.NewInt(int64(msg.Tier)), nil))
amount = new(big.Int).Div(amount, new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(msg.Tier)), nil))
tx = types.NewTransaction(f.nonce+uint64(len(f.reqs)), address, amount, 21000, f.price, nil)
} else {
tokenInfo, ok := f.bep2eInfos[msg.Symbol]
if !ok {
f.lock.Unlock()
log.Warn("Failed to find symbol", "symbol", msg.Symbol)
continue
}
input, err := f.bep2eAbi.Pack("transfer", address, &tokenInfo.Amount)
if err != nil {
f.lock.Unlock()
log.Warn("Failed to pack transfer transaction", "err", err)
continue
}
tx = types.NewTransaction(f.nonce+uint64(len(f.reqs)), tokenInfo.Contract, nil, 420000, f.price, input)
}
signed, err := f.keystore.SignTx(f.account, tx, f.config.ChainID)
if err != nil {
f.lock.Unlock()

View File

@@ -53,7 +53,13 @@
<span class="input-group-btn">
<button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Give me BNB <i class="fa fa-caret-down" aria-hidden="true"></i></button>
<ul class="dropdown-menu dropdown-menu-right">{{range $idx, $amount := .Amounts}}
<li><a style="text-align: center;" onclick="tier={{$idx}}; {{if $.Recaptcha}}grecaptcha.execute(){{else}}submit({{$idx}}){{end}}">{{$amount}}</a></li>{{end}}
<li><a style="text-align: center;" onclick="tier={{$idx}};symbol='BNB'; {{if $.Recaptcha}}grecaptcha.execute(){{else}}submit({{$idx}}){{end}}">{{$amount}}</a></li>{{end}}
</ul>
</span>
<span class="input-group-btn">
<button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Peggy tokens<i class="fa fa-caret-down" aria-hidden="true"></i></button>
<ul class="dropdown-menu dropdown-menu-right"> {{range $symbol, $bep2eInfo := .Bep2eInfos}}
<li><a style="text-align: center;" onclick="symbol={{$symbol}}; {{if $.Recaptcha}}grecaptcha.execute(){{else}}submitBep2e({{$symbol}}){{end}}">{{$bep2eInfo.AmountStr}} {{$symbol}}</a></li>{{end}}
</ul>
</span>
</div>{{if .Recaptcha}}
@@ -85,6 +91,7 @@
var attempt = 0;
var server;
var tier = 0;
var symbol="";
var requests = [];
// Define a function that creates closures to drop old requests
@@ -100,7 +107,7 @@
};
// Define the function that submits a gist url to the server
var submit = function({{if .Recaptcha}}captcha{{end}}) {
server.send(JSON.stringify({url: $("#url")[0].value, tier: tier{{if .Recaptcha}}, captcha: captcha{{end}}}));{{if .Recaptcha}}
server.send(JSON.stringify({url: $("#url")[0].value, symbol: symbol, tier: tier{{if .Recaptcha}}, captcha: captcha{{end}}}));{{if .Recaptcha}}
grecaptcha.reset();{{end}}
};
// Define a method to reconnect upon server loss

File diff suppressed because one or more lines are too long

View File

@@ -54,11 +54,15 @@ const (
systemRewardPercent = 4 // it means 1/2^4 = 1/16 percentage of gas fee incoming will be distributed to system
// genesis contracts
ValidatorContract = "0x0000000000000000000000000000000000001000"
SlashContract = "0x0000000000000000000000000000000000001001"
SystemRewardContract = "0x0000000000000000000000000000000000001002"
LightClientContract = "0x0000000000000000000000000000000000001003"
RelayerHubContract = "0x0000000000000000000000000000000000001006"
ValidatorContract = "0x0000000000000000000000000000000000001000"
SlashContract = "0x0000000000000000000000000000000000001001"
SystemRewardContract = "0x0000000000000000000000000000000000001002"
LightClientContract = "0x0000000000000000000000000000000000001003"
TokenHubContract = "0x0000000000000000000000000000000000001004"
RelayerIncentivizeContract = "0x0000000000000000000000000000000000001005"
RelayerHubContract = "0x0000000000000000000000000000000000001006"
GovHubContract = "0x0000000000000000000000000000000000001007"
CrossChainContract = "0x0000000000000000000000000000000000002000"
)
var (
@@ -69,11 +73,15 @@ var (
maxSystemBalance = new(big.Int).Mul(big.NewInt(100), big.NewInt(params.Ether))
systemContracts = map[common.Address]bool{
common.HexToAddress(ValidatorContract): true,
common.HexToAddress(SlashContract): true,
common.HexToAddress(SystemRewardContract): true,
common.HexToAddress(LightClientContract): true,
common.HexToAddress(RelayerHubContract): true,
common.HexToAddress(ValidatorContract): true,
common.HexToAddress(SlashContract): true,
common.HexToAddress(SystemRewardContract): true,
common.HexToAddress(LightClientContract): true,
common.HexToAddress(RelayerHubContract): true,
common.HexToAddress(GovHubContract): true,
common.HexToAddress(TokenHubContract): true,
common.HexToAddress(RelayerIncentivizeContract): true,
common.HexToAddress(CrossChainContract): true,
}
)
@@ -148,7 +156,7 @@ func isToSystemContract(to common.Address) bool {
}
// ecrecover extracts the Ethereum account address from a signed header.
func ecrecover(header *types.Header, sigCache *lru.ARCCache) (common.Address, error) {
func ecrecover(header *types.Header, sigCache *lru.ARCCache, chainId *big.Int) (common.Address, error) {
// If the signature's already cached, return that
hash := header.Hash()
if address, known := sigCache.Get(hash); known {
@@ -161,7 +169,7 @@ func ecrecover(header *types.Header, sigCache *lru.ARCCache) (common.Address, er
signature := header.Extra[len(header.Extra)-extraSeal:]
// Recover the public key and the Ethereum address
pubkey, err := crypto.Ecrecover(SealHash(header).Bytes(), signature)
pubkey, err := crypto.Ecrecover(SealHash(header, chainId).Bytes(), signature)
if err != nil {
return common.Address{}, err
}
@@ -179,9 +187,9 @@ func ecrecover(header *types.Header, sigCache *lru.ARCCache) (common.Address, er
// Note, the method requires the extra data to be at least 65 bytes, otherwise it
// panics. This is done to avoid accidentally using both forms (signature present
// or not), which could be abused to produce different hashes for the same header.
func ParliaRLP(header *types.Header) []byte {
func ParliaRLP(header *types.Header, chainId *big.Int) []byte {
b := new(bytes.Buffer)
encodeSigHeader(b, header)
encodeSigHeader(b, header, chainId)
return b.Bytes()
}
@@ -265,7 +273,7 @@ func (p *Parlia) IsSystemTransaction(tx *types.Transaction, header *types.Header
if err != nil {
return false, errors.New("UnAuthorized transaction")
}
if sender == header.Coinbase && isToSystemContract(*tx.To()) {
if sender == header.Coinbase && isToSystemContract(*tx.To()) && tx.GasPrice().Cmp(big.NewInt(0)) == 0 {
return true, nil
}
return false, nil
@@ -330,7 +338,6 @@ func (p *Parlia) verifyHeader(chain consensus.ChainReader, header *types.Header,
if len(header.Extra) < extraVanity+extraSeal {
return errMissingSignature
}
// check extra data
isEpoch := number%p.config.Epoch == 0
@@ -491,7 +498,7 @@ func (p *Parlia) snapshot(chain consensus.ChainReader, number uint64, hash commo
headers[i], headers[len(headers)-1-i] = headers[len(headers)-1-i], headers[i]
}
snap, err := snap.apply(headers, chain, parents)
snap, err := snap.apply(headers, chain, parents, p.chainConfig.ChainID)
if err != nil {
return nil, err
}
@@ -539,7 +546,7 @@ func (p *Parlia) verifySeal(chain consensus.ChainReader, header *types.Header, p
}
// Resolve the authorization key and check against validators
signer, err := ecrecover(header, p.signatures)
signer, err := ecrecover(header, p.signatures, p.chainConfig.ChainID)
if err != nil {
return err
}
@@ -653,7 +660,7 @@ func (p *Parlia) Finalize(chain consensus.ChainReader, header *types.Header, sta
// No block rewards in PoA, so the state remains as is and uncles are dropped
cx := chainContext{Chain: chain, parlia: p}
if header.Number.Cmp(common.Big1) == 0 {
err := p.initContract(state, header, cx, txs, receipts, systemTxs, usedGas)
err := p.initContract(state, header, cx, txs, receipts, systemTxs, usedGas, false)
if err != nil {
log.Error("init contract failed")
}
@@ -674,14 +681,15 @@ func (p *Parlia) Finalize(chain consensus.ChainReader, header *types.Header, sta
}
if !signedRecently {
log.Info("slash validator", "block hash", header.Hash(), "address", spoiledVal)
err = p.slash(spoiledVal, state, header, cx, txs, receipts, systemTxs, usedGas)
err = p.slash(spoiledVal, state, header, cx, txs, receipts, systemTxs, usedGas, false)
if err != nil {
panic(err)
// it is possible that slash validator failed because of the slash channel is disabled.
log.Error("slash validator failed", "block hash", header.Hash(), "address", spoiledVal)
}
}
}
val := header.Coinbase
err := p.distributeIncoming(val, state, header, cx, txs, receipts, systemTxs, usedGas)
err := p.distributeIncoming(val, state, header, cx, txs, receipts, systemTxs, usedGas, false)
if err != nil {
panic(err)
}
@@ -706,7 +714,7 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainReader, header *types.
receipts = make([]*types.Receipt, 0)
}
if header.Number.Cmp(common.Big1) == 0 {
err := p.initContract(state, header, cx, &txs, &receipts, nil, &header.GasUsed)
err := p.initContract(state, header, cx, &txs, &receipts, nil, &header.GasUsed, true)
if err != nil {
log.Error("init contract failed")
}
@@ -726,16 +734,21 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainReader, header *types.
}
}
if !signedRecently {
err = p.slash(spoiledVal, state, header, cx, &txs, &receipts, nil, &header.GasUsed)
err = p.slash(spoiledVal, state, header, cx, &txs, &receipts, nil, &header.GasUsed, true)
if err != nil {
panic(err)
// it is possible that slash validator failed because of the slash channel is disabled.
log.Error("slash validator failed", "block hash", header.Hash(), "address", spoiledVal)
}
}
}
err := p.distributeIncoming(p.val, state, header, cx, &txs, &receipts, nil, &header.GasUsed)
err := p.distributeIncoming(p.val, state, header, cx, &txs, &receipts, nil, &header.GasUsed, true)
if err != nil {
panic(err)
}
// should not happen. Once happen, stop the node is better than broadcast the block
if header.GasLimit < header.GasUsed {
panic("Gas consumption of system txs exceed the gas limit")
}
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
header.UncleHash = types.CalcUncleHash(nil)
@@ -808,7 +821,7 @@ func (p *Parlia) Seal(chain consensus.ChainReader, block *types.Block, results c
log.Info("Sealing block with", "number", number, "delay", delay, "headerDifficulty", header.Difficulty, "val", val.Hex())
// Sign all the things!
sig, err := signFn(accounts.Account{Address: val}, accounts.MimetypeParlia, ParliaRLP(header))
sig, err := signFn(accounts.Account{Address: val}, accounts.MimetypeParlia, ParliaRLP(header, p.chainConfig.ChainID))
if err != nil {
return err
}
@@ -826,7 +839,7 @@ func (p *Parlia) Seal(chain consensus.ChainReader, block *types.Block, results c
select {
case results <- block.WithSeal(header):
default:
log.Warn("Sealing result is not read by miner", "sealhash", SealHash(header))
log.Warn("Sealing result is not read by miner", "sealhash", SealHash(header, p.chainConfig.ChainID))
}
}()
@@ -856,7 +869,7 @@ func CalcDifficulty(snap *Snapshot, signer common.Address) *big.Int {
// SealHash returns the hash of a block prior to it being sealed.
func (p *Parlia) SealHash(header *types.Header) common.Hash {
return SealHash(header)
return SealHash(header, p.chainConfig.ChainID)
}
// APIs implements consensus.Engine, returning the user facing RPC API to query snapshot.
@@ -923,7 +936,7 @@ func (p *Parlia) getCurrentValidators(blockHash common.Hash) ([]common.Address,
// slash spoiled validators
func (p *Parlia) distributeIncoming(val common.Address, state *state.StateDB, header *types.Header, chain core.ChainContext,
txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64) error {
txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error {
coinbase := header.Coinbase
balance := state.GetBalance(consensus.SystemAddress)
if balance.Cmp(common.Big0) <= 0 {
@@ -937,7 +950,7 @@ func (p *Parlia) distributeIncoming(val common.Address, state *state.StateDB, he
var rewards = new(big.Int)
rewards = rewards.Rsh(balance, systemRewardPercent)
if rewards.Cmp(common.Big0) > 0 {
err := p.distributeToSystem(rewards, state, header, chain, txs, receipts, receivedTxs, usedGas)
err := p.distributeToSystem(rewards, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
if err != nil {
return err
}
@@ -946,12 +959,12 @@ func (p *Parlia) distributeIncoming(val common.Address, state *state.StateDB, he
}
}
log.Info("distribute to validator contract", "block hash", header.Hash(), "amount", balance)
return p.distributeToValidator(balance, val, state, header, chain, txs, receipts, receivedTxs, usedGas)
return p.distributeToValidator(balance, val, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
}
// slash spoiled validators
func (p *Parlia) slash(spoiledVal common.Address, state *state.StateDB, header *types.Header, chain core.ChainContext,
txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64) error {
txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error {
// method
method := "slash"
@@ -966,16 +979,16 @@ func (p *Parlia) slash(spoiledVal common.Address, state *state.StateDB, header *
// get system message
msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(SlashContract), data, common.Big0)
// apply message
return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas)
return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
}
// init contract
func (p *Parlia) initContract(state *state.StateDB, header *types.Header, chain core.ChainContext,
txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64) error {
txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error {
// method
method := "init"
// contracts
contracts := []string{ValidatorContract, SlashContract, LightClientContract, RelayerHubContract}
contracts := []string{ValidatorContract, SlashContract, LightClientContract, RelayerHubContract, TokenHubContract, RelayerIncentivizeContract, CrossChainContract}
// get packed data
data, err := p.validatorSetABI.Pack(method)
if err != nil {
@@ -986,7 +999,7 @@ func (p *Parlia) initContract(state *state.StateDB, header *types.Header, chain
msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(c), data, common.Big0)
// apply message
log.Info("init contract", "block hash", header.Hash(), "contract", c)
err = p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas)
err = p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
if err != nil {
return err
}
@@ -995,17 +1008,17 @@ func (p *Parlia) initContract(state *state.StateDB, header *types.Header, chain
}
func (p *Parlia) distributeToSystem(amount *big.Int, state *state.StateDB, header *types.Header, chain core.ChainContext,
txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64) error {
txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error {
// get system message
msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(SystemRewardContract), nil, amount)
// apply message
return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas)
return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
}
// slash spoiled validators
func (p *Parlia) distributeToValidator(amount *big.Int, validator common.Address,
state *state.StateDB, header *types.Header, chain core.ChainContext,
txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64) error {
txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error {
// method
method := "deposit"
@@ -1020,7 +1033,7 @@ func (p *Parlia) distributeToValidator(amount *big.Int, validator common.Address
// get system message
msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(ValidatorContract), data, amount)
// apply message
return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas)
return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
}
// get system message
@@ -1043,13 +1056,13 @@ func (p *Parlia) applyTransaction(
header *types.Header,
chainContext core.ChainContext,
txs *[]*types.Transaction, receipts *[]*types.Receipt,
receivedTxs *[]*types.Transaction, usedGas *uint64,
receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool,
) (err error) {
nonce := state.GetNonce(msg.From())
expectedTx := types.NewTransaction(nonce, *msg.To(), msg.Value(), msg.Gas(), msg.GasPrice(), msg.Data())
expectedHash := p.signer.Hash(expectedTx)
if msg.From() == p.val {
if msg.From() == p.val && mining {
expectedTx, err = p.signTxFn(accounts.Account{Address: msg.From()}, expectedTx, p.chainConfig.ChainID)
if err != nil {
return err
@@ -1096,15 +1109,16 @@ func (p *Parlia) applyTransaction(
// =========================== utility function ==========================
// SealHash returns the hash of a block prior to it being sealed.
func SealHash(header *types.Header) (hash common.Hash) {
func SealHash(header *types.Header, chainId *big.Int) (hash common.Hash) {
hasher := sha3.NewLegacyKeccak256()
encodeSigHeader(hasher, header)
encodeSigHeader(hasher, header, chainId)
hasher.Sum(hash[:0])
return hash
}
func encodeSigHeader(w io.Writer, header *types.Header) {
func encodeSigHeader(w io.Writer, header *types.Header, chainId *big.Int) {
err := rlp.Encode(w, []interface{}{
chainId,
header.ParentHash,
header.UncleHash,
header.Coinbase,
@@ -1180,3 +1194,4 @@ func applyMessage(
}
return msg.Gas() - returnGas, err
}

View File

@@ -20,6 +20,7 @@ import (
"bytes"
"encoding/json"
"errors"
"math/big"
"sort"
"github.com/ethereum/go-ethereum/common"
@@ -123,7 +124,7 @@ func (s *Snapshot) copy() *Snapshot {
return cpy
}
func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainReader, parents []*types.Header) (*Snapshot, error) {
func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainReader, parents []*types.Header, chainId *big.Int) (*Snapshot, error) {
// Allow passing in no headers for cleaner code
if len(headers) == 0 {
return s, nil
@@ -153,7 +154,7 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainReader, p
delete(snap.Recents, number-limit)
}
// Resolve the authorization key and check against signers
validator, err := ecrecover(header, s.sigCache)
validator, err := ecrecover(header, s.sigCache, chainId)
if err != nil {
return nil, err
}

View File

@@ -162,10 +162,11 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
// as every returning call will return new data anyway.
in.returnData = nil
// TODO temporary fix for issue
// Don't bother with the execution if there's no code.
if len(contract.Code) == 0 {
return nil, nil
}
//if len(contract.Code) == 0 {
// return nil, nil
//}
var (
op OpCode // current opcode

View File

@@ -502,12 +502,13 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block,
// Generate the next state snapshot fast without tracing
msg, _ := tx.AsMessage(signer)
vmctx := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil)
if posa, ok := api.eth.engine.(consensus.PoSA); ok && msg.From() == block.Header().Coinbase &&
posa.IsSystemContract(msg.To()) {
balance := statedb.GetBalance(consensus.SystemAddress)
if balance.Cmp(common.Big0) > 0 {
statedb.SetBalance(consensus.SystemAddress, big.NewInt(0))
statedb.AddBalance(block.Header().Coinbase, balance)
if posa, ok := api.eth.engine.(consensus.PoSA); ok {
if isSystem, _ := posa.IsSystemTransaction(tx, block.Header()); isSystem {
balance := statedb.GetBalance(consensus.SystemAddress)
if balance.Cmp(common.Big0) > 0 {
statedb.SetBalance(consensus.SystemAddress, big.NewInt(0))
statedb.AddBalance(block.Header().Coinbase, balance)
}
}
}
vmenv := vm.NewEVM(vmctx, statedb, api.eth.blockchain.Config(), vm.Config{})
@@ -767,7 +768,7 @@ func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, v
// Run the transaction with tracing enabled.
vmenv := vm.NewEVM(vmctx, statedb, api.eth.blockchain.Config(), vm.Config{Debug: true, Tracer: tracer})
if posa, ok := api.eth.engine.(consensus.PoSA); ok && message.From() == vmctx.Coinbase &&
posa.IsSystemContract(message.To()) {
posa.IsSystemContract(message.To()) && message.GasPrice().Cmp(big.NewInt(0)) == 0 {
balance := statedb.GetBalance(consensus.SystemAddress)
if balance.Cmp(common.Big0) > 0 {
statedb.SetBalance(consensus.SystemAddress, big.NewInt(0))
@@ -822,12 +823,13 @@ func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int, ree
for idx, tx := range block.Transactions() {
// Assemble the transaction call message and return if the requested offset
msg, _ := tx.AsMessage(signer)
if posa, ok := api.eth.engine.(consensus.PoSA); ok && msg.From() == block.Header().Coinbase &&
posa.IsSystemContract(msg.To()) {
balance := statedb.GetBalance(consensus.SystemAddress)
if balance.Cmp(common.Big0) > 0 {
statedb.SetBalance(consensus.SystemAddress, big.NewInt(0))
statedb.AddBalance(block.Header().Coinbase, balance)
if posa, ok := api.eth.engine.(consensus.PoSA); ok {
if isSystem, _ := posa.IsSystemTransaction(tx, block.Header()); isSystem {
balance := statedb.GetBalance(consensus.SystemAddress)
if balance.Cmp(common.Big0) > 0 {
statedb.SetBalance(consensus.SystemAddress, big.NewInt(0))
statedb.AddBalance(block.Header().Coinbase, balance)
}
}
}
context := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil)

View File

@@ -37,7 +37,7 @@ const (
)
const (
maxUncleDist = 7 // Maximum allowed backward distance from the chain head
maxUncleDist = 11 // Maximum allowed backward distance from the chain head
maxQueueDist = 32 // Maximum allowed distance from the chain head to queue
hashLimit = 256 // Maximum number of unique blocks a peer may have announced
blockLimit = 64 // Maximum number of unique blocks a peer may have delivered

View File

@@ -56,7 +56,7 @@ const (
resubmitAdjustChanSize = 10
// miningLogAtDepth is the number of confirmations before logging successful mining.
miningLogAtDepth = 15
miningLogAtDepth = 11
// minRecommitInterval is the minimal time interval to recreate the mining block with
// any newly arrived transactions.
@@ -75,7 +75,7 @@ const (
intervalAdjustBias = 200 * 1000.0 * 1000.0
// staleThreshold is the maximum depth of the acceptable stale block.
staleThreshold = 7
staleThreshold = 11
)
var (
@@ -356,7 +356,7 @@ func (w *worker) newWorkLoop(recommit time.Duration) {
commit(false, commitInterruptNewHead)
case head := <-w.chainHeadCh:
if !w.isRunning(){
if !w.isRunning() {
continue
}
clearPending(head.Block.NumberU64())
@@ -732,6 +732,7 @@ func (w *worker) commitTransactions(txs *types.TransactionsByPriceAndNonce, coin
if w.current.gasPool == nil {
w.current.gasPool = new(core.GasPool).AddGas(w.current.header.GasLimit)
w.current.gasPool.SubGas(params.SystemTxsGas)
}
var coalescedLogs []*types.Log

View File

@@ -19,21 +19,22 @@ package params
import "math/big"
const (
GasLimitBoundDivisor uint64 = 256 // The bound divisor of the gas limit, used in update calculations.
GasLimitBoundDivisor uint64 = 256 // The bound divisor of the gas limit, used in update calculations.
MinGasLimit uint64 = 5000 // Minimum the gas limit may ever be.
GenesisGasLimit uint64 = 4712388 // Gas limit of the Genesis block.
MaximumExtraDataSize uint64 = 32 // Maximum size extra data may be after Genesis.
ExpByteGas uint64 = 10 // Times ceil(log256(exponent)) for the EXP instruction.
SloadGas uint64 = 50 // Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added.
CallValueTransferGas uint64 = 9000 // Paid for CALL when the value transfer is non-zero.
CallNewAccountGas uint64 = 25000 // Paid for CALL when the destination address didn't exist prior.
TxGas uint64 = 21000 // Per transaction not creating a contract. NOTE: Not payable on data of calls between transactions.
TxGasContractCreation uint64 = 53000 // Per transaction that creates a contract. NOTE: Not payable on data of calls between transactions.
TxDataZeroGas uint64 = 4 // Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions.
QuadCoeffDiv uint64 = 512 // Divisor for the quadratic particle of the memory cost equation.
LogDataGas uint64 = 8 // Per byte in a LOG* operation's data.
CallStipend uint64 = 2300 // Free gas given at beginning of call.
MaximumExtraDataSize uint64 = 32 // Maximum size extra data may be after Genesis.
ExpByteGas uint64 = 10 // Times ceil(log256(exponent)) for the EXP instruction.
SloadGas uint64 = 50 // Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added.
CallValueTransferGas uint64 = 9000 // Paid for CALL when the value transfer is non-zero.
CallNewAccountGas uint64 = 25000 // Paid for CALL when the destination address didn't exist prior.
TxGas uint64 = 21000 // Per transaction not creating a contract. NOTE: Not payable on data of calls between transactions.
SystemTxsGas uint64 = 100000 // The gas reserved for system txs; only for parlia consensus
TxGasContractCreation uint64 = 53000 // Per transaction that creates a contract. NOTE: Not payable on data of calls between transactions.
TxDataZeroGas uint64 = 4 // Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions.
QuadCoeffDiv uint64 = 512 // Divisor for the quadratic particle of the memory cost equation.
LogDataGas uint64 = 8 // Per byte in a LOG* operation's data.
CallStipend uint64 = 2300 // Free gas given at beginning of call.
Sha3Gas uint64 = 30 // Once per SHA3 operation.
Sha3WordGas uint64 = 6 // Once per word of the SHA3 operation's data.

View File

@@ -23,8 +23,8 @@ import (
const (
VersionMajor = 1 // Major version component of the current release
VersionMinor = 0 // Minor version component of the current release
VersionPatch = 0 // Patch version component of the current release
VersionMeta = "alpha.0" // Version metadata to append to the version string
VersionPatch = 0 // Patch version component of the current release
VersionMeta = "beta.0" // Version metadata to append to the version string
)
// Version holds the textual version string.

View File

@@ -285,7 +285,7 @@ func (api *SignerAPI) determineSignatureFormat(ctx context.Context, contentType
header.Extra = newExtra
}
// Get back the rlp data, encoded by us
sighash, parliaRlp, err := parliaHeaderHashAndRlp(header)
sighash, parliaRlp, err := parliaHeaderHashAndRlp(header, api.chainID)
if err != nil {
return nil, useEthereumV, err
}
@@ -351,13 +351,13 @@ func cliqueHeaderHashAndRlp(header *types.Header) (hash, rlp []byte, err error)
return hash, rlp, err
}
func parliaHeaderHashAndRlp(header *types.Header) (hash, rlp []byte, err error) {
func parliaHeaderHashAndRlp(header *types.Header, chainId *big.Int) (hash, rlp []byte, err error) {
if len(header.Extra) < 65 {
err = fmt.Errorf("clique header extradata too short, %d < 65", len(header.Extra))
return
}
rlp = parlia.ParliaRLP(header)
hash = parlia.SealHash(header).Bytes()
rlp = parlia.ParliaRLP(header, chainId)
hash = parlia.SealHash(header, chainId).Bytes()
return hash, rlp, err
}