diff --git a/Dockerfile.node b/Dockerfile.node index ea5ff41ae3..b02c243475 100644 --- a/Dockerfile.node +++ b/Dockerfile.node @@ -27,6 +27,7 @@ ENV NETWORK_ID '89' ENV WS_SECRET '' ENV NETSTATS_HOST 'netstats-server' ENV NETSTATS_PORT '3000' +ENV ANNOUNCE_TXS '' RUN apk add --no-cache ca-certificates diff --git a/cmd/tomo/main.go b/cmd/tomo/main.go index 48a4bdcc4f..9a125d0485 100644 --- a/cmd/tomo/main.go +++ b/cmd/tomo/main.go @@ -120,6 +120,7 @@ var ( //utils.GpoPercentileFlag, //utils.ExtraDataFlag, configFileFlag, + utils.AnnounceTxsFlag, } rpcFlags = []cli.Flag{ diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 27c3077242..f158819e42 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -113,6 +113,10 @@ func NewApp(gitCommit, usage string) *cli.App { var ( // General settings + AnnounceTxsFlag = cli.BoolFlag{ + Name: "announce-txs", + Usage: "Always commit transactions", + } DataDirFlag = DirectoryFlag{ Name: "datadir", Usage: "Data directory for the databases and keystore", @@ -897,6 +901,9 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) { if ctx.GlobalIsSet(NoUSBFlag.Name) { cfg.NoUSB = ctx.GlobalBool(NoUSBFlag.Name) } + if ctx.GlobalIsSet(AnnounceTxsFlag.Name) { + cfg.AnnounceTxs = ctx.GlobalBool(AnnounceTxsFlag.Name) + } } func setGPO(ctx *cli.Context, cfg *gasprice.Config) { diff --git a/consensus/consensus.go b/consensus/consensus.go index be5e661c12..b02afa63c4 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -58,7 +58,7 @@ type Engine interface { // VerifyHeader checks whether a header conforms to the consensus rules of a // given engine. Verifying the seal may be done optionally here, or explicitly // via the VerifySeal method. - VerifyHeader(chain ChainReader, header *types.Header, seal bool) error + VerifyHeader(chain ChainReader, header *types.Header, fullVerify bool) error // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers // concurrently. The method returns a quit channel to abort the operations and diff --git a/consensus/posv/posv.go b/consensus/posv/posv.go index d060fd05eb..7c45902e5c 100644 --- a/consensus/posv/posv.go +++ b/consensus/posv/posv.go @@ -46,8 +46,6 @@ import ( const ( inmemorySnapshots = 128 // Number of recent vote snapshots to keep in memory - inmemorySignatures = 4096 // Number of recent block signatures to keep in memory - wiggleTime = 500 * time.Millisecond // Random delay (per signer) to allow concurrent signers M2ByteLength = 4 ) @@ -58,8 +56,7 @@ type Masternode struct { // Posv proof-of-stake-voting protocol constants. var ( - epochLength = uint64(30000) // Default number of blocks after which to checkpoint and reset the pending votes - blockPeriod = uint64(15) // Default minimum difference between two consecutive block's timestamps + epochLength = uint64(900) // Default number of blocks after which to checkpoint and reset the pending votes extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal @@ -226,11 +223,11 @@ type Posv struct { HookReward func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) error HookPenalty func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error) - HookValidator func(header *types.Header, signers []common.Address) error + HookValidator func(header *types.Header, signers []common.Address) ([]byte, error) HookVerifyMNs func(header *types.Header, signers []common.Address) error } -// New creates a Posv proof-of-stake-voting consensus engine with the initial +// New creates a PoSV proof-of-stake-voting consensus engine with the initial // signers set to the ones provided by the user. func New(config *params.PosvConfig, db ethdb.Database) *Posv { // Set any missing consensus parameters to their defaults @@ -261,20 +258,20 @@ func (c *Posv) Author(header *types.Header) (common.Address, error) { } // VerifyHeader checks whether a header conforms to the consensus rules. -func (c *Posv) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error { - return c.verifyHeaderWithCache(chain, header, nil) +func (c *Posv) VerifyHeader(chain consensus.ChainReader, header *types.Header, fullVerify bool) error { + return c.verifyHeaderWithCache(chain, header, nil, fullVerify) } // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers. The // method returns a quit channel to abort the operations and a results channel to // retrieve the async verifications (the order is that of the input slice). -func (c *Posv) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { +func (c *Posv) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, fullVerifies []bool) (chan<- struct{}, <-chan error) { abort := make(chan struct{}) results := make(chan error, len(headers)) go func() { for i, header := range headers { - err := c.verifyHeaderWithCache(chain, header, headers[:i]) + err := c.verifyHeaderWithCache(chain, header, headers[:i], fullVerifies[i]) select { case <-abort: @@ -286,12 +283,12 @@ func (c *Posv) VerifyHeaders(chain consensus.ChainReader, headers []*types.Heade return abort, results } -func (c *Posv) verifyHeaderWithCache(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error { +func (c *Posv) verifyHeaderWithCache(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error { _, check := c.verifiedHeaders.Get(header.Hash()) if check { return nil } - err := c.verifyHeader(chain, header, parents) + err := c.verifyHeader(chain, header, parents, fullVerify) if err == nil { c.verifiedHeaders.Add(header.Hash(), true) } @@ -302,15 +299,19 @@ func (c *Posv) verifyHeaderWithCache(chain consensus.ChainReader, header *types. // caller may optionally pass in a batch of parents (ascending order) to avoid // looking those up from the database. This is useful for concurrently verifying // a batch of new headers. -func (c *Posv) verifyHeader(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error { +func (c *Posv) verifyHeader(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error { if header.Number == nil { return errUnknownBlock } number := header.Number.Uint64() - - // Don't waste time checking blocks from the future - if header.Time.Cmp(big.NewInt(time.Now().Unix())) > 0 { - return consensus.ErrFutureBlock + if fullVerify { + if header.Number.Uint64() > c.config.Epoch && len(header.Validator) == 0 { + return consensus.ErrNoValidatorSignature + } + // Don't waste time checking blocks from the future + if header.Time.Cmp(big.NewInt(time.Now().Unix())) > 0 { + return consensus.ErrFutureBlock + } } // Checkpoint blocks need to enforce zero beneficiary checkpoint := (number % c.config.Epoch) == 0 @@ -344,29 +345,23 @@ func (c *Posv) verifyHeader(chain consensus.ChainReader, header *types.Header, p if header.MixDigest != (common.Hash{}) { return errInvalidMixDigest } - // Ensure that the block doesn't contain any uncles which are meaningless in PoA + // Ensure that the block doesn't contain any uncles which are meaningless in PoSV if header.UncleHash != uncleHash { return errInvalidUncleHash } - // Ensure that the block's difficulty is meaningful (may not be correct at this point) - if number > 0 { - if header.Difficulty == nil || (header.Difficulty.Cmp(diffInTurn) != 0 && header.Difficulty.Cmp(diffNoTurn) != 0) { - return errInvalidDifficulty - } - } // If all checks passed, validate any special fields for hard forks if err := misc.VerifyForkHashes(chain.Config(), header, false); err != nil { return err } // All basic checks passed, verify cascading fields - return c.verifyCascadingFields(chain, header, parents) + return c.verifyCascadingFields(chain, header, parents, fullVerify) } // verifyCascadingFields verifies all the header fields that are not standalone, // rather depend on a batch of previous headers. The caller may optionally pass // in a batch of parents (ascending order) to avoid looking those up from the // database. This is useful for concurrently verifying a batch of new headers. -func (c *Posv) verifyCascadingFields(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error { +func (c *Posv) verifyCascadingFields(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error { // The genesis block is the always valid dead-end number := header.Number.Uint64() if number == 0 { @@ -385,9 +380,6 @@ func (c *Posv) verifyCascadingFields(chain consensus.ChainReader, header *types. if parent.Time.Uint64()+c.config.Period > header.Time.Uint64() { return ErrInvalidTimestamp } - if header.Number.Uint64() > c.config.Epoch && len(header.Validator) == 0 { - return consensus.ErrNoValidatorSignature - } // Retrieve the snapshot needed to verify this header and cache it snap, err := c.snapshot(chain, number-1, header.ParentHash, parents) if err != nil { @@ -429,7 +421,7 @@ func (c *Posv) verifyCascadingFields(chain consensus.ChainReader, header *types. } } // All basic checks passed, verify the seal and return - return c.verifySeal(chain, header, parents) + return c.verifySeal(chain, header, parents, fullVerify) } func (c *Posv) GetSnapshot(chain consensus.ChainReader, header *types.Header) (*Snapshot, error) { @@ -471,7 +463,7 @@ func (c *Posv) GetMasternodes(chain consensus.ChainReader, header *types.Header) func (c *Posv) GetPeriod() uint64 { return c.config.Period } -func WhoIsCreator(snap *Snapshot, header *types.Header) (common.Address, error) { +func whoIsCreator(snap *Snapshot, header *types.Header) (common.Address, error) { if header.Number.Uint64() == 0 { return common.Address{}, errors.New("Don't take block 0") } @@ -482,31 +474,38 @@ func WhoIsCreator(snap *Snapshot, header *types.Header) (common.Address, error) return m, nil } -func YourTurn(masternodes []common.Address, snap *Snapshot, header *types.Header, cur common.Address) (int, int, bool, error) { +func (c *Posv) YourTurn(chain consensus.ChainReader, parent *types.Header, signer common.Address) (int, int, int, bool, error) { + masternodes := c.GetMasternodes(chain, parent) masternodes = masternodes[:len(masternodes)/2+1] + snap, err := c.GetSnapshot(chain, parent) + if err != nil { + log.Error("Failed when trying to commit new work", "err", err) + return 0, -1, -1, false, err + } if len(masternodes) == 0 { - return -1, -1, true, nil + return 0, -1, -1, false, errors.New("Masternodes not found") } pre := common.Address{} // masternode[0] has chance to create block 1 - var err error preIndex := -1 - if header.Number.Uint64() != 0 { - pre, err = WhoIsCreator(snap, header) + if parent.Number.Uint64() != 0 { + pre, err = whoIsCreator(snap, parent) if err != nil { - return 0, 0, false, err + return 0, 0, 0, false, err } preIndex = position(masternodes, pre) } - curIndex := position(masternodes, cur) - log.Info("Masternodes cycle info", "number of masternodes", len(masternodes), "previous", pre, "position", preIndex, "current", cur, "position", curIndex) + curIndex := position(masternodes, signer) + if signer == c.signer { + log.Info("Masternodes cycle info", "number of masternodes", len(masternodes), "previous", pre, "position", preIndex, "current", signer, "position", curIndex) + } for i, s := range masternodes { fmt.Printf("%d - %s\n", i, s.String()) } if (preIndex+1)%len(masternodes) == curIndex { - return preIndex, curIndex, true, nil + return len(masternodes), preIndex, curIndex, true, nil } - return preIndex, curIndex, false, nil + return len(masternodes), preIndex, curIndex, false, nil } // snapshot retrieves the authorization snapshot at a given point in time. @@ -534,7 +533,7 @@ func (c *Posv) snapshot(chain consensus.ChainReader, number uint64, hash common. // If we're at block zero, make a snapshot if number == 0 { genesis := chain.GetHeaderByNumber(0) - if err := c.VerifyHeader(chain, genesis, false); err != nil { + if err := c.VerifyHeader(chain, genesis, true); err != nil { return nil, err } signers := make([]common.Address, (len(genesis.Extra)-extraVanity-extraSeal)/common.AddressLength) @@ -599,7 +598,7 @@ func (c *Posv) VerifyUncles(chain consensus.ChainReader, block *types.Block) err // VerifySeal implements consensus.Engine, checking whether the signature contained // in the header satisfies the consensus protocol requirements. func (c *Posv) VerifySeal(chain consensus.ChainReader, header *types.Header) error { - return c.verifySeal(chain, header, nil) + return c.verifySeal(chain, header, nil, true) } // verifySeal checks whether the signature contained in the header satisfies the @@ -608,7 +607,7 @@ func (c *Posv) VerifySeal(chain consensus.ChainReader, header *types.Header) err // from. // verifySeal also checks the pair of creator-validator set in the header satisfies // the double validation. -func (c *Posv) verifySeal(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error { +func (c *Posv) verifySeal(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error { // Verifying the genesis block is not supported number := header.Number.Uint64() if number == 0 { @@ -625,6 +624,20 @@ func (c *Posv) verifySeal(chain consensus.ChainReader, header *types.Header, par if err != nil { return err } + var parent *types.Header + if len(parents) > 0 { + parent = parents[len(parents)-1] + } else { + parent = chain.GetHeader(header.ParentHash, number-1) + } + difficulty := c.calcDifficulty(chain, parent, creator) + log.Debug("verify seal block", "number", header.Number, "hash", header.Hash(), "block difficulty", header.Difficulty, "calc difficulty", difficulty, "creator", creator) + // Ensure that the block's difficulty is meaningful (may not be correct at this point) + if number > 0 { + if header.Difficulty.Int64() != difficulty.Int64() { + return errInvalidDifficulty + } + } masternodes := c.GetMasternodes(chain, header) mstring := []string{} for _, m := range masternodes { @@ -664,7 +677,7 @@ func (c *Posv) verifySeal(chain consensus.ChainReader, header *types.Header, par // header must contain validator info following double validation design // start checking from epoch 2nd. - if header.Number.Uint64() > c.config.Epoch { + if header.Number.Uint64() > c.config.Epoch && fullVerify { validator, err := c.RecoverValidator(header) if err != nil { return err @@ -742,38 +755,49 @@ func (c *Posv) Prepare(chain consensus.ChainReader, header *types.Header) error } c.lock.RUnlock() } + parent := chain.GetHeader(header.ParentHash, number-1) + if parent == nil { + return consensus.ErrUnknownAncestor + } // Set the correct difficulty - header.Difficulty = big.NewInt(1) - + header.Difficulty = c.calcDifficulty(chain, parent, c.signer) + log.Debug("CalcDifficulty ", "number", header.Number, "difficulty", header.Difficulty) // Ensure the extra data has all it's components if len(header.Extra) < extraVanity { header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, extraVanity-len(header.Extra))...) } header.Extra = header.Extra[:extraVanity] - signers := snap.GetSigners() - if number%c.config.Epoch == 0 { + masternodes := snap.GetSigners() + if number > 0 && number%c.config.Epoch == 0 { if c.HookPenalty != nil { - penSigners, err := c.HookPenalty(chain, number) + penMasternodes, err := c.HookPenalty(chain, number) if err != nil { return err } - if len(penSigners) > 0 { - // Keep remove penalty signer out of signer list. - signers = common.RemoveItemFromArray(signers, penSigners) - for _, address := range penSigners { - log.Debug("Penalty Info", "address", address, "number", number) + if len(penMasternodes) > 0 { + // penalize bad masternode(s) + masternodes = common.RemoveItemFromArray(masternodes, penMasternodes) + for _, address := range penMasternodes { + log.Debug("Penalty status", "address", address, "block number", number) } - header.Penalties = common.ExtractAddressToBytes(penSigners) + header.Penalties = common.ExtractAddressToBytes(penMasternodes) } } - // Prevent penaltied signer in 4 epocs ago jump into signer list. + // Prevent penalized masternode(s) within 4 recent epochs for i := 1; i <= common.LimitPenaltyEpoch; i++ { if number > uint64(i)*c.config.Epoch { - signers = RemovePenaltiesFromBlock(chain, signers, number-uint64(i)*c.config.Epoch) + masternodes = RemovePenaltiesFromBlock(chain, masternodes, number-uint64(i)*c.config.Epoch) } } - for _, signer := range signers { - header.Extra = append(header.Extra, signer[:]...) + for _, masternode := range masternodes { + header.Extra = append(header.Extra, masternode[:]...) + } + if c.HookValidator != nil { + validators, err := c.HookValidator(header, masternodes) + if err != nil { + return err + } + header.Validators = validators } } header.Extra = append(header.Extra, make([]byte, extraSeal)...) @@ -782,20 +806,11 @@ func (c *Posv) Prepare(chain consensus.ChainReader, header *types.Header) error header.MixDigest = common.Hash{} // Ensure the timestamp has the correct delay - parent := chain.GetHeader(header.ParentHash, number-1) - if parent == nil { - return consensus.ErrUnknownAncestor - } + header.Time = new(big.Int).Add(parent.Time, new(big.Int).SetUint64(c.config.Period)) if header.Time.Int64() < time.Now().Unix() { header.Time = big.NewInt(time.Now().Unix()) } - if c.HookValidator != nil { - c.HookValidator(header, signers) - if err != nil { - return err - } - } return nil } @@ -807,23 +822,14 @@ func (c *Posv) UpdateMasternodes(chain consensus.ChainReader, header *types.Head if err != nil { return err } - currentSigners := snap.GetSigners() - proposedSigners := make(map[common.Address]struct{}) - // count all addresses in ms to be masternode + newMasternodes := make(map[common.Address]struct{}) for _, m := range ms { - proposedSigners[m.Address] = struct{}{} - snap.Signers[m.Address] = struct{}{} - } - // deactivate current masternodes which aren't in ms - for _, s := range currentSigners { - if _, ok := proposedSigners[s]; !ok { - delete(snap.Signers, s) - } + newMasternodes[m.Address] = struct{}{} } + snap.Signers = newMasternodes nm := []string{} - newSigners := snap.GetSigners() - for _, n := range newSigners { - nm = append(nm, n.String()) + for _, n := range ms { + nm = append(nm, n.Address.String()) } c.recents.Add(snap.Hash, snap) log.Info("New set of masternodes has been updated to snapshot", "number", snap.Number, "hash", snap.Hash, "new masternodes", nm) @@ -834,7 +840,6 @@ func (c *Posv) UpdateMasternodes(chain consensus.ChainReader, header *types.Head // rewards given, and returns the final block. func (c *Posv) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { // set block reward - // FIXME: unit Ether could be too plump number := header.Number.Uint64() rCheckpoint := chain.Config().Posv.RewardCheckpoint @@ -844,7 +849,7 @@ func (c *Posv) Finalize(chain consensus.ChainReader, header *types.Header, state } } - // No block rewards in PoA, so the state remains as is and uncles are dropped + // the state remains as is and uncles are dropped header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) header.UncleHash = types.CalcUncleHash(nil) @@ -909,7 +914,7 @@ func (c *Posv) Seal(chain consensus.ChainReader, block *types.Block, stop <-chan if limit := uint64(2); number < limit || seen > number-limit { // Only take into account the non-epoch blocks if number%c.config.Epoch != 0 { - log.Info("Debugging", "len(masternodes)", len(masternodes), "number", number, "limit", limit, "seen", seen, "recent", recent.String(), "snap.Recents", snap.Recents) + log.Info("len(masternodes)", len(masternodes), "number", number, "limit", limit, "seen", seen, "recent", recent.String(), "snap.Recents", snap.Recents) log.Info("Signed recently, must wait for others") <-stop return nil, nil @@ -937,21 +942,15 @@ func (c *Posv) Seal(chain consensus.ChainReader, block *types.Block, stop <-chan // that a new block should have based on the previous blocks in the chain and the // current signer. func (c *Posv) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int { - snap, err := c.snapshot(chain, parent.Number.Uint64(), parent.Hash(), nil) - if err != nil { - return nil - } - return CalcDifficulty(snap, c.signer) + return c.calcDifficulty(chain, parent, c.signer) } -// CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty -// that a new block should have based on the previous blocks in the chain and the -// current signer. -func CalcDifficulty(snap *Snapshot, signer common.Address) *big.Int { - if snap.inturn(snap.Number+1, signer) { - return new(big.Int).Set(diffInTurn) +func (c *Posv) calcDifficulty(chain consensus.ChainReader, parent *types.Header, signer common.Address) *big.Int { + len, preIndex, curIndex, _, err := c.YourTurn(chain, parent, signer) + if err != nil { + return big.NewInt(int64(len + curIndex - preIndex)) } - return new(big.Int).Set(diffNoTurn) + return big.NewInt(int64(len - Hop(len, preIndex, curIndex))) } // APIs implements consensus.Engine, returning the user facing RPC API to allow @@ -1006,18 +1005,18 @@ func (c *Posv) GetMasternodesFromCheckpointHeader(preCheckpointHeader *types.Hea } // Extract validators from byte array. -func RemovePenaltiesFromBlock(chain consensus.ChainReader, signers []common.Address, epochNumber uint64) []common.Address { +func RemovePenaltiesFromBlock(chain consensus.ChainReader, masternodes []common.Address, epochNumber uint64) []common.Address { if epochNumber <= 0 { - return signers + return masternodes } header := chain.GetHeaderByNumber(epochNumber) block := chain.GetBlock(header.Hash(), epochNumber) penalties := block.Penalties() if penalties != nil { prevPenalties := common.ExtractAddressFromBytes(penalties) - signers = common.RemoveItemFromArray(signers, prevPenalties) + masternodes = common.RemoveItemFromArray(masternodes, prevPenalties) } - return signers + return masternodes } // Get masternodes address from checkpoint Header. @@ -1066,3 +1065,14 @@ func ExtractValidatorsFromBytes(byteValidators []byte) []int64 { return validators } + +func Hop(len, pre, cur int) int { + switch { + case pre < cur: + return cur - (pre + 1) + case pre > cur: + return (len - pre) + (cur - 1) + default: + return len - 1 + } +} diff --git a/contracts/blocksigner/contract/blocksigner.go b/contracts/blocksigner/contract/blocksigner.go index 34bc1061b2..385c1f525c 100644 --- a/contracts/blocksigner/contract/blocksigner.go +++ b/contracts/blocksigner/contract/blocksigner.go @@ -377,7 +377,7 @@ func (_BlockSigner *BlockSignerFilterer) WatchSign(opts *bind.WatchOpts, sink ch const SafeMathABI = "[]" // SafeMathBin is the compiled bytecode used for deploying new contracts. -const SafeMathBin = `0x604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a72305820a3f63b465e1cf25f306b1eb1efefc8dac3c38993a7340f69d8b470c3bf599ff30029` +const SafeMathBin = `0x604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146060604052600080fd00a165627a7a72305820b9407d48ebc7efee5c9f08b3b3a957df2939281f5913225e8c1291f069b900490029` // DeploySafeMath deploys a new Ethereum contract, binding an instance of SafeMath to it. func DeploySafeMath(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *SafeMath, error) { diff --git a/contracts/multisigwallet/contract/multisigwallet.go b/contracts/multisigwallet/contract/multisigwallet.go index 6d56f2fe45..8cd1109197 100644 --- a/contracts/multisigwallet/contract/multisigwallet.go +++ b/contracts/multisigwallet/contract/multisigwallet.go @@ -19,7 +19,7 @@ import ( const MultiSigWalletABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"owners\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"removeOwner\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"transactionId\",\"type\":\"uint256\"}],\"name\":\"revokeConfirmation\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"isOwner\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"address\"}],\"name\":\"confirmations\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"pending\",\"type\":\"bool\"},{\"name\":\"executed\",\"type\":\"bool\"}],\"name\":\"getTransactionCount\",\"outputs\":[{\"name\":\"count\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"addOwner\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"transactionId\",\"type\":\"uint256\"}],\"name\":\"isConfirmed\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"transactionId\",\"type\":\"uint256\"}],\"name\":\"getConfirmationCount\",\"outputs\":[{\"name\":\"count\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transactions\",\"outputs\":[{\"name\":\"destination\",\"type\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\"},{\"name\":\"executed\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getOwners\",\"outputs\":[{\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"from\",\"type\":\"uint256\"},{\"name\":\"to\",\"type\":\"uint256\"},{\"name\":\"pending\",\"type\":\"bool\"},{\"name\":\"executed\",\"type\":\"bool\"}],\"name\":\"getTransactionIds\",\"outputs\":[{\"name\":\"_transactionIds\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"transactionId\",\"type\":\"uint256\"}],\"name\":\"getConfirmations\",\"outputs\":[{\"name\":\"_confirmations\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"transactionCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_required\",\"type\":\"uint256\"}],\"name\":\"changeRequirement\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"transactionId\",\"type\":\"uint256\"}],\"name\":\"confirmTransaction\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"destination\",\"type\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"submitTransaction\",\"outputs\":[{\"name\":\"transactionId\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"MAX_OWNER_COUNT\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"required\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"owner\",\"type\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"replaceOwner\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"transactionId\",\"type\":\"uint256\"}],\"name\":\"executeTransaction\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_owners\",\"type\":\"address[]\"},{\"name\":\"_required\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"transactionId\",\"type\":\"uint256\"}],\"name\":\"Confirmation\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"transactionId\",\"type\":\"uint256\"}],\"name\":\"Revocation\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"transactionId\",\"type\":\"uint256\"}],\"name\":\"Submission\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"transactionId\",\"type\":\"uint256\"}],\"name\":\"Execution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"transactionId\",\"type\":\"uint256\"}],\"name\":\"ExecutionFailure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnerAddition\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnerRemoval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"RequirementChange\",\"type\":\"event\"}]" // MultiSigWalletBin is the compiled bytecode used for deploying new contracts. -const MultiSigWalletBin = `0x60806040523480156200001157600080fd5b50604051620016a2380380620016a283398101604052805160208201519101805190919060009082603282118015906200004b5750818111155b80156200005757508015155b80156200006357508115155b15156200006f57600080fd5b600092505b845183101562000147576002600086858151811015156200009157fe5b6020908102909101810151600160a060020a031682528101919091526040016000205460ff16158015620000e757508483815181101515620000cf57fe5b90602001906020020151600160a060020a0316600014155b1515620000f357600080fd5b60016002600087868151811015156200010857fe5b602090810291909101810151600160a060020a03168252810191909152604001600020805460ff19169115159190911790556001929092019162000074565b84516200015c9060039060208801906200016e565b50505060049190915550620002029050565b828054828255906000526020600020908101928215620001c6579160200282015b82811115620001c65782518254600160a060020a031916600160a060020a039091161782556020909201916001909101906200018f565b50620001d4929150620001d8565b5090565b620001ff91905b80821115620001d4578054600160a060020a0319168155600101620001df565b90565b61149080620002126000396000f30060806040526004361061011c5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663025e7c27811461015e578063173825d91461019257806320ea8d86146101b35780632f54bf6e146101cb5780633411c81c1461020057806354741525146102245780637065cb4814610255578063784547a7146102765780638b51d13f1461028e5780639ace38c2146102a6578063a0e67e2b14610361578063a8abe69a146103c6578063b5dc40c3146103eb578063b77bf60014610403578063ba51a6df14610418578063c01a8c8414610430578063c642747414610448578063d74f8edd146104b1578063dc8452cd146104c6578063e20056e6146104db578063ee22610b14610502575b600034111561015c5760408051348152905133917fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c919081900360200190a25b005b34801561016a57600080fd5b5061017660043561051a565b60408051600160a060020a039092168252519081900360200190f35b34801561019e57600080fd5b5061015c600160a060020a0360043516610542565b3480156101bf57600080fd5b5061015c6004356106b9565b3480156101d757600080fd5b506101ec600160a060020a0360043516610773565b604080519115158252519081900360200190f35b34801561020c57600080fd5b506101ec600435600160a060020a0360243516610788565b34801561023057600080fd5b50610243600435151560243515156107a8565b60408051918252519081900360200190f35b34801561026157600080fd5b5061015c600160a060020a0360043516610814565b34801561028257600080fd5b506101ec600435610939565b34801561029a57600080fd5b506102436004356109bd565b3480156102b257600080fd5b506102be600435610a2c565b6040518085600160a060020a0316600160a060020a031681526020018481526020018060200183151515158152602001828103825284818151815260200191508051906020019080838360005b8381101561032357818101518382015260200161030b565b50505050905090810190601f1680156103505780820380516001836020036101000a031916815260200191505b509550505050505060405180910390f35b34801561036d57600080fd5b50610376610aea565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156103b257818101518382015260200161039a565b505050509050019250505060405180910390f35b3480156103d257600080fd5b5061037660043560243560443515156064351515610b4d565b3480156103f757600080fd5b50610376600435610c86565b34801561040f57600080fd5b50610243610dff565b34801561042457600080fd5b5061015c600435610e05565b34801561043c57600080fd5b5061015c600435610e84565b34801561045457600080fd5b50604080516020600460443581810135601f8101849004840285018401909552848452610243948235600160a060020a0316946024803595369594606494920191908190840183828082843750949750610f4f9650505050505050565b3480156104bd57600080fd5b50610243610f6e565b3480156104d257600080fd5b50610243610f73565b3480156104e757600080fd5b5061015c600160a060020a0360043581169060243516610f79565b34801561050e57600080fd5b5061015c600435611103565b600380548290811061052857fe5b600091825260209091200154600160a060020a0316905081565b600033301461055057600080fd5b600160a060020a038216600090815260026020526040902054829060ff16151561057957600080fd5b600160a060020a0383166000908152600260205260408120805460ff1916905591505b600354600019018210156106545782600160a060020a03166003838154811015156105c357fe5b600091825260209091200154600160a060020a03161415610649576003805460001981019081106105f057fe5b60009182526020909120015460038054600160a060020a03909216918490811061061657fe5b9060005260206000200160006101000a815481600160a060020a030219169083600160a060020a03160217905550610654565b60019091019061059c565b60038054600019019061066790826113a3565b5060035460045411156106805760035461068090610e05565b604051600160a060020a038416907f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9090600090a2505050565b3360008181526002602052604090205460ff1615156106d757600080fd5b60008281526001602090815260408083203380855292529091205483919060ff16151561070357600080fd5b600084815260208190526040902060030154849060ff161561072457600080fd5b6000858152600160209081526040808320338085529252808320805460ff191690555187927ff6a317157440607f36269043eb55f1287a5a19ba2216afeab88cd46cbcfb88e991a35050505050565b60026020526000908152604090205460ff1681565b600160209081526000928352604080842090915290825290205460ff1681565b6000805b60055481101561080d578380156107d5575060008181526020819052604090206003015460ff16155b806107f957508280156107f9575060008181526020819052604090206003015460ff165b15610805576001820191505b6001016107ac565b5092915050565b33301461082057600080fd5b600160a060020a038116600090815260026020526040902054819060ff161561084857600080fd5b81600160a060020a038116151561085e57600080fd5b6003805490506001016004546032821115801561087b5750818111155b801561088657508015155b801561089157508115155b151561089c57600080fd5b600160a060020a038516600081815260026020526040808220805460ff1916600190811790915560038054918201815583527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b01805473ffffffffffffffffffffffffffffffffffffffff191684179055517ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d9190a25050505050565b600080805b6003548110156109b6576000848152600160205260408120600380549192918490811061096757fe5b6000918252602080832090910154600160a060020a0316835282019290925260400190205460ff161561099b576001820191505b6004548214156109ae57600192506109b6565b60010161093e565b5050919050565b6000805b600354811015610a2657600083815260016020526040812060038054919291849081106109ea57fe5b6000918252602080832090910154600160a060020a0316835282019290925260400190205460ff1615610a1e576001820191505b6001016109c1565b50919050565b6000602081815291815260409081902080546001808301546002808501805487516101009582161595909502600019011691909104601f8101889004880284018801909652858352600160a060020a0390931695909491929190830182828015610ad75780601f10610aac57610100808354040283529160200191610ad7565b820191906000526020600020905b815481529060010190602001808311610aba57829003601f168201915b5050506003909301549192505060ff1684565b60606003805480602002602001604051908101604052809291908181526020018280548015610b4257602002820191906000526020600020905b8154600160a060020a03168152600190910190602001808311610b24575b505050505090505b90565b606080600080600554604051908082528060200260200182016040528015610b7f578160200160208202803883390190505b50925060009150600090505b600554811015610c0657858015610bb4575060008181526020819052604090206003015460ff16155b80610bd85750848015610bd8575060008181526020819052604090206003015460ff165b15610bfe57808383815181101515610bec57fe5b60209081029091010152600191909101905b600101610b8b565b878703604051908082528060200260200182016040528015610c32578160200160208202803883390190505b5093508790505b86811015610c7b578281815181101515610c4f57fe5b9060200190602002015184898303815181101515610c6957fe5b60209081029091010152600101610c39565b505050949350505050565b606080600080600380549050604051908082528060200260200182016040528015610cbb578160200160208202803883390190505b50925060009150600090505b600354811015610d785760008581526001602052604081206003805491929184908110610cf057fe5b6000918252602080832090910154600160a060020a0316835282019290925260400190205460ff1615610d70576003805482908110610d2b57fe5b6000918252602090912001548351600160a060020a0390911690849084908110610d5157fe5b600160a060020a03909216602092830290910190910152600191909101905b600101610cc7565b81604051908082528060200260200182016040528015610da2578160200160208202803883390190505b509350600090505b81811015610df7578281815181101515610dc057fe5b906020019060200201518482815181101515610dd857fe5b600160a060020a03909216602092830290910190910152600101610daa565b505050919050565b60055481565b333014610e1157600080fd5b6003548160328211801590610e265750818111155b8015610e3157508015155b8015610e3c57508115155b1515610e4757600080fd5b60048390556040805184815290517fa3f1ee9126a074d9326c682f561767f710e927faa811f7a99829d49dc421797a9181900360200190a1505050565b3360008181526002602052604090205460ff161515610ea257600080fd5b6000828152602081905260409020548290600160a060020a03161515610ec757600080fd5b60008381526001602090815260408083203380855292529091205484919060ff1615610ef257600080fd5b6000858152600160208181526040808420338086529252808420805460ff1916909317909255905187927f4a504a94899432a9846e1aa406dceb1bcfd538bb839071d49d1e5e23f5be30ef91a3610f4885611103565b5050505050565b6000610f5c8484846112b3565b9050610f6781610e84565b9392505050565b603281565b60045481565b6000333014610f8757600080fd5b600160a060020a038316600090815260026020526040902054839060ff161515610fb057600080fd5b600160a060020a038316600090815260026020526040902054839060ff1615610fd857600080fd5b600092505b6003548310156110695784600160a060020a031660038481548110151561100057fe5b600091825260209091200154600160a060020a0316141561105e578360038481548110151561102b57fe5b9060005260206000200160006101000a815481600160a060020a030219169083600160a060020a03160217905550611069565b600190920191610fdd565b600160a060020a03808616600081815260026020526040808220805460ff1990811690915593881682528082208054909416600117909355915190917f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9091a2604051600160a060020a038516907ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d90600090a25050505050565b3360008181526002602052604081205490919060ff16151561112457600080fd5b60008381526001602090815260408083203380855292529091205484919060ff16151561115057600080fd5b600085815260208190526040902060030154859060ff161561117157600080fd5b61117a86610939565b156112ab576000868152602081905260409081902060038101805460ff19166001908117909155815481830154935160028085018054959b50600160a060020a03909316959492939192839285926000199183161561010002919091019091160480156112285780601f106111fd57610100808354040283529160200191611228565b820191906000526020600020905b81548152906001019060200180831161120b57829003601f168201915b505091505060006040518083038185875af192505050156112735760405186907f33e13ecb54c3076d8e8bb8c2881800a4d972b792045ffae98fdf46df365fed7590600090a26112ab565b60405186907f526441bb6c1aba3c9a4a6ca1d6545da9c2333c8c48343ef398eb858d72b7923690600090a260038501805460ff191690555b505050505050565b600083600160a060020a03811615156112cb57600080fd5b60055460408051608081018252600160a060020a0388811682526020808301898152838501898152600060608601819052878152808452959095208451815473ffffffffffffffffffffffffffffffffffffffff19169416939093178355516001830155925180519496509193909261134b9260028501929101906113cc565b50606091909101516003909101805460ff191691151591909117905560058054600101905560405182907fc0ba8fe4b176c1714197d43b9cc6bcf797a4a7461c5fe8d0ef6e184ae7601e5190600090a2509392505050565b8154818355818111156113c7576000838152602090206113c791810190830161144a565b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061140d57805160ff191683800117855561143a565b8280016001018555821561143a579182015b8281111561143a57825182559160200191906001019061141f565b5061144692915061144a565b5090565b610b4a91905b8082111561144657600081556001016114505600a165627a7a723058205abf7d18955ab47351d41bfbeff39ba447c3c2d681f3180795235e9f260da4ba0029` +const MultiSigWalletBin = `0x606060405234156200001057600080fd5b6040516200174f3803806200174f83398101604052808051820191906020018051915060009050825182603282111580156200004c5750818111155b80156200005857508015155b80156200006457508115155b15156200007057600080fd5b600092505b84518310156200014157600260008685815181106200009057fe5b90602001906020020151600160a060020a0316815260208101919091526040016000205460ff16158015620000e35750848381518110620000cd57fe5b90602001906020020151600160a060020a031615155b1515620000ef57600080fd5b6001600260008786815181106200010257fe5b90602001906020020151600160a060020a031681526020810191909152604001600020805460ff19169115159190911790556001929092019162000075565b60038580516200015692916020019062000168565b50505060049190915550620001fe9050565b828054828255906000526020600020908101928215620001c2579160200282015b82811115620001c25782518254600160a060020a031916600160a060020a03919091161782556020929092019160019091019062000189565b50620001d0929150620001d4565b5090565b620001fb91905b80821115620001d0578054600160a060020a0319168155600101620001db565b90565b611541806200020e6000396000f30060606040526004361061011c5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663025e7c278114610165578063173825d91461019757806320ea8d86146101b65780632f54bf6e146101cc5780633411c81c146101ff57806354741525146102215780637065cb4814610250578063784547a71461026f5780638b51d13f146102855780639ace38c21461029b578063a0e67e2b14610349578063a8abe69a146103af578063b5dc40c3146103d2578063b77bf600146103e8578063ba51a6df146103fb578063c01a8c8414610411578063c642747414610427578063d74f8edd1461048c578063dc8452cd1461049f578063e20056e6146104b2578063ee22610b146104d7575b60003411156101635733600160a060020a03167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c3460405190815260200160405180910390a25b005b341561017057600080fd5b61017b6004356104ed565b604051600160a060020a03909116815260200160405180910390f35b34156101a257600080fd5b610163600160a060020a0360043516610515565b34156101c157600080fd5b6101636004356106aa565b34156101d757600080fd5b6101eb600160a060020a0360043516610788565b604051901515815260200160405180910390f35b341561020a57600080fd5b6101eb600435600160a060020a036024351661079d565b341561022c57600080fd5b61023e600435151560243515156107bd565b60405190815260200160405180910390f35b341561025b57600080fd5b610163600160a060020a0360043516610829565b341561027a57600080fd5b6101eb600435610965565b341561029057600080fd5b61023e6004356109e9565b34156102a657600080fd5b6102b1600435610a58565b604051600160a060020a038516815260208101849052811515606082015260806040820181815290820184818151815260200191508051906020019080838360005b8381101561030b5780820151838201526020016102f3565b50505050905090810190601f1680156103385780820380516001836020036101000a031916815260200191505b509550505050505060405180910390f35b341561035457600080fd5b61035c610b36565b60405160208082528190810183818151815260200191508051906020019060200280838360005b8381101561039b578082015183820152602001610383565b505050509050019250505060405180910390f35b34156103ba57600080fd5b61035c60043560243560443515156064351515610b9f565b34156103dd57600080fd5b61035c600435610cc7565b34156103f357600080fd5b61023e610e2b565b341561040657600080fd5b610163600435610e31565b341561041c57600080fd5b610163600435610ec4565b341561043257600080fd5b61023e60048035600160a060020a03169060248035919060649060443590810190830135806020601f82018190048102016040519081016040528181529291906020840183838082843750949650610fb295505050505050565b341561049757600080fd5b61023e610fd1565b34156104aa57600080fd5b61023e610fd6565b34156104bd57600080fd5b610163600160a060020a0360043581169060243516610fdc565b34156104e257600080fd5b61016360043561118a565b60038054829081106104fb57fe5b600091825260209091200154600160a060020a0316905081565b600030600160a060020a031633600160a060020a031614151561053757600080fd5b600160a060020a038216600090815260026020526040902054829060ff16151561056057600080fd5b600160a060020a0383166000908152600260205260408120805460ff1916905591505b600354600019018210156106435782600160a060020a03166003838154811015156105aa57fe5b600091825260209091200154600160a060020a03161415610638576003805460001981019081106105d757fe5b60009182526020909120015460038054600160a060020a0390921691849081106105fd57fe5b6000918252602090912001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055610643565b600190910190610583565b6003805460001901906106569082611442565b50600354600454111561066f5760035461066f90610e31565b82600160a060020a03167f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9060405160405180910390a2505050565b33600160a060020a03811660009081526002602052604090205460ff1615156106d257600080fd5b600082815260016020908152604080832033600160a060020a038116855292529091205483919060ff16151561070757600080fd5b600084815260208190526040902060030154849060ff161561072857600080fd5b6000858152600160209081526040808320600160a060020a033316808552925291829020805460ff1916905586917ff6a317157440607f36269043eb55f1287a5a19ba2216afeab88cd46cbcfb88e9905160405180910390a35050505050565b60026020526000908152604090205460ff1681565b600160209081526000928352604080842090915290825290205460ff1681565b6000805b600554811015610822578380156107ea575060008181526020819052604090206003015460ff16155b8061080e575082801561080e575060008181526020819052604090206003015460ff165b1561081a576001820191505b6001016107c1565b5092915050565b30600160a060020a031633600160a060020a031614151561084957600080fd5b600160a060020a038116600090815260026020526040902054819060ff161561087157600080fd5b81600160a060020a038116151561088757600080fd5b600380549050600101600454603282111580156108a45750818111155b80156108af57508015155b80156108ba57508115155b15156108c557600080fd5b600160a060020a0385166000908152600260205260409020805460ff1916600190811790915560038054909181016108fd8382611442565b506000918252602090912001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0387169081179091557ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d60405160405180910390a25050505050565b600080805b6003548110156109e2576000848152600160205260408120600380549192918490811061099357fe5b6000918252602080832090910154600160a060020a0316835282019290925260400190205460ff16156109c7576001820191505b6004548214156109da57600192506109e2565b60010161096a565b5050919050565b6000805b600354811015610a525760008381526001602052604081206003805491929184908110610a1657fe5b6000918252602080832090910154600160a060020a0316835282019290925260400190205460ff1615610a4a576001820191505b6001016109ed565b50919050565b60006020528060005260406000206000915090508060000160009054906101000a9004600160a060020a031690806001015490806002018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610b235780601f10610af857610100808354040283529160200191610b23565b820191906000526020600020905b815481529060010190602001808311610b0657829003601f168201915b5050506003909301549192505060ff1684565b610b3e61146b565b6003805480602002602001604051908101604052809291908181526020018280548015610b9457602002820191906000526020600020905b8154600160a060020a03168152600190910190602001808311610b76575b505050505090505b90565b610ba761146b565b610baf61146b565b600080600554604051805910610bc25750595b9080825280602002602001820160405250925060009150600090505b600554811015610c5757858015610c07575060008181526020819052604090206003015460ff16155b80610c2b5750848015610c2b575060008181526020819052604090206003015460ff165b15610c4f5780838381518110610c3d57fe5b60209081029091010152600191909101905b600101610bde565b878703604051805910610c675750595b908082528060200260200182016040525093508790505b86811015610cbc57828181518110610c9257fe5b906020019060200201518489830381518110610caa57fe5b60209081029091010152600101610c7e565b505050949350505050565b610ccf61146b565b610cd761146b565b6003546000908190604051805910610cec5750595b9080825280602002602001820160405250925060009150600090505b600354811015610db45760008581526001602052604081206003805491929184908110610d3157fe5b6000918252602080832090910154600160a060020a0316835282019290925260400190205460ff1615610dac576003805482908110610d6c57fe5b600091825260209091200154600160a060020a0316838381518110610d8d57fe5b600160a060020a03909216602092830290910190910152600191909101905b600101610d08565b81604051805910610dc25750595b90808252806020026020018201604052509350600090505b81811015610e2357828181518110610dee57fe5b90602001906020020151848281518110610e0457fe5b600160a060020a03909216602092830290910190910152600101610dda565b505050919050565b60055481565b30600160a060020a031633600160a060020a0316141515610e5157600080fd5b6003548160328211801590610e665750818111155b8015610e7157508015155b8015610e7c57508115155b1515610e8757600080fd5b60048390557fa3f1ee9126a074d9326c682f561767f710e927faa811f7a99829d49dc421797a8360405190815260200160405180910390a1505050565b33600160a060020a03811660009081526002602052604090205460ff161515610eec57600080fd5b6000828152602081905260409020548290600160a060020a03161515610f1157600080fd5b600083815260016020908152604080832033600160a060020a038116855292529091205484919060ff1615610f4557600080fd5b6000858152600160208181526040808420600160a060020a033316808652925292839020805460ff191690921790915586917f4a504a94899432a9846e1aa406dceb1bcfd538bb839071d49d1e5e23f5be30ef905160405180910390a3610fab8561118a565b5050505050565b6000610fbf848484611345565b9050610fca81610ec4565b9392505050565b603281565b60045481565b600030600160a060020a031633600160a060020a0316141515610ffe57600080fd5b600160a060020a038316600090815260026020526040902054839060ff16151561102757600080fd5b600160a060020a038316600090815260026020526040902054839060ff161561104f57600080fd5b600092505b6003548310156110e85784600160a060020a031660038481548110151561107757fe5b600091825260209091200154600160a060020a031614156110dd57836003848154811015156110a257fe5b6000918252602090912001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03929092169190911790556110e8565b600190920191611054565b600160a060020a03808616600081815260026020526040808220805460ff199081169091559388168252908190208054909316600117909255907f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b90905160405180910390a283600160a060020a03167ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d60405160405180910390a25050505050565b33600160a060020a03811660009081526002602052604081205490919060ff1615156111b557600080fd5b600083815260016020908152604080832033600160a060020a038116855292529091205484919060ff1615156111ea57600080fd5b600085815260208190526040902060030154859060ff161561120b57600080fd5b61121486610965565b1561133d576000868152602081905260409081902060038101805460ff19166001908117909155815490820154919750600160a060020a03169160028801905180828054600181600116156101000203166002900480156112b65780601f1061128b576101008083540402835291602001916112b6565b820191906000526020600020905b81548152906001019060200180831161129957829003601f168201915b505091505060006040518083038185875af1925050501561130357857f33e13ecb54c3076d8e8bb8c2881800a4d972b792045ffae98fdf46df365fed7560405160405180910390a261133d565b857f526441bb6c1aba3c9a4a6ca1d6545da9c2333c8c48343ef398eb858d72b7923660405160405180910390a260038501805460ff191690555b505050505050565b600083600160a060020a038116151561135d57600080fd5b600554915060806040519081016040908152600160a060020a0387168252602080830187905281830186905260006060840181905285815290819052208151815473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0391909116178155602082015181600101556040820151816002019080516113e892916020019061147d565b506060820151600391909101805460ff191691151591909117905550600580546001019055817fc0ba8fe4b176c1714197d43b9cc6bcf797a4a7461c5fe8d0ef6e184ae7601e5160405160405180910390a2509392505050565b815481835581811511611466576000838152602090206114669181019083016114fb565b505050565b60206040519081016040526000815290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106114be57805160ff19168380011785556114eb565b828001600101855582156114eb579182015b828111156114eb5782518255916020019190600101906114d0565b506114f79291506114fb565b5090565b610b9c91905b808211156114f757600081556001016115015600a165627a7a72305820d42d65ce3cd184b1c0e98ae5fe9841a03ddd21c504e98c38f8d89df83b2b6be60029` // DeployMultiSigWallet deploys a new Ethereum contract, binding an instance of MultiSigWallet to it. func DeployMultiSigWallet(auth *bind.TransactOpts, backend bind.ContractBackend, _owners []common.Address, _required *big.Int) (common.Address, *types.Transaction, *MultiSigWallet, error) { diff --git a/contracts/randomize/contract/randomize.go b/contracts/randomize/contract/randomize.go index 52579c1701..d2b81772da 100644 --- a/contracts/randomize/contract/randomize.go +++ b/contracts/randomize/contract/randomize.go @@ -16,7 +16,7 @@ import ( const SafeMathABI = "[]" // SafeMathBin is the compiled bytecode used for deploying new contracts. -const SafeMathBin = `0x604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146080604052600080fd00a165627a7a72305820ea3f7b50706b29b7324f2b7bc6c5eec464df491d2c006d76decd3a344ef24b5b0029` +const SafeMathBin = `0x604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f30073000000000000000000000000000000000000000030146060604052600080fd00a165627a7a72305820b9407d48ebc7efee5c9f08b3b3a957df2939281f5913225e8c1291f069b900490029` // DeploySafeMath deploys a new Ethereum contract, binding an instance of SafeMath to it. func DeploySafeMath(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *SafeMath, error) { @@ -177,7 +177,7 @@ func (_SafeMath *SafeMathTransactorRaw) Transact(opts *bind.TransactOpts, method const TomoRandomizeABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"_validator\",\"type\":\"address\"}],\"name\":\"getSecret\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_secret\",\"type\":\"bytes32[]\"}],\"name\":\"setSecret\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_validator\",\"type\":\"address\"}],\"name\":\"getOpening\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_opening\",\"type\":\"bytes32\"}],\"name\":\"setOpening\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}]" // TomoRandomizeBin is the compiled bytecode used for deploying new contracts. -const TomoRandomizeBin = `0x608060405234801561001057600080fd5b50610335806100206000396000f3006080604052600436106100615763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663284180fc811461006657806334d38600146100e4578063d442d6cc1461013b578063e11f5ba21461017b575b600080fd5b34801561007257600080fd5b5061009473ffffffffffffffffffffffffffffffffffffffff60043516610193565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156100d05781810151838201526020016100b8565b505050509050019250505060405180910390f35b3480156100f057600080fd5b50604080516020600480358082013583810280860185019096528085526101399536959394602494938501929182918501908490808284375094975061020b9650505050505050565b005b34801561014757600080fd5b5061016973ffffffffffffffffffffffffffffffffffffffff60043516610250565b60408051918252519081900360200190f35b34801561018757600080fd5b50610139600435610278565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260208181526040918290208054835181840281018401909452808452606093928301828280156101ff57602002820191906000526020600020905b815481526001909101906020018083116101ea575b50505050509050919050565b610384430661032081101561021f57600080fd5b610352811061022d57600080fd5b33600090815260208181526040909120835161024b9285019061029f565b505050565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604090205490565b610384430661035281101561028c57600080fd5b5033600090815260016020526040902055565b8280548282559060005260206000209081019282156102dc579160200282015b828111156102dc57825182556020909201916001909101906102bf565b506102e89291506102ec565b5090565b61030691905b808211156102e857600081556001016102f2565b905600a165627a7a72305820524cb2eeb0cc4214180425f822fd315cd15fd8352a830bbd9846b46133730a100029` +const TomoRandomizeBin = `0x6060604052341561000f57600080fd5b6103368061001e6000396000f3006060604052600436106100615763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663284180fc811461006657806334d38600146100d8578063d442d6cc14610129578063e11f5ba21461015a575b600080fd5b341561007157600080fd5b610085600160a060020a0360043516610170565b60405160208082528190810183818151815260200191508051906020019060200280838360005b838110156100c45780820151838201526020016100ac565b505050509050019250505060405180910390f35b34156100e357600080fd5b61012760046024813581810190830135806020818102016040519081016040528093929190818152602001838360200280828437509496506101f395505050505050565b005b341561013457600080fd5b610148600160a060020a0360043516610243565b60405190815260200160405180910390f35b341561016557600080fd5b61012760043561025e565b61017861028e565b60008083600160a060020a0316600160a060020a031681526020019081526020016000208054806020026020016040519081016040528092919081815260200182805480156101e757602002820191906000526020600020905b815481526001909101906020018083116101d2575b50505050509050919050565b610384430661032081101561020757600080fd5b610352811061021557600080fd5b600160a060020a033316600090815260208190526040902082805161023e9291602001906102a0565b505050565b600160a060020a031660009081526001602052604090205490565b610384430661035281101561027257600080fd5b50600160a060020a033316600090815260016020526040902055565b60206040519081016040526000815290565b8280548282559060005260206000209081019282156102dd579160200282015b828111156102dd57825182556020909201916001909101906102c0565b506102e99291506102ed565b5090565b61030791905b808211156102e957600081556001016102f3565b905600a165627a7a7230582034991c8dc4001fc254f3ba2811c05d2e7d29bee3908946ca56d1545b2c852de20029` // DeployTomoRandomize deploys a new Ethereum contract, binding an instance of TomoRandomize to it. func DeployTomoRandomize(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *TomoRandomize, error) { diff --git a/contracts/validator/contract/TomoValidator.sol b/contracts/validator/contract/TomoValidator.sol index ecaa8145e5..c49a07ecc5 100644 --- a/contracts/validator/contract/TomoValidator.sol +++ b/contracts/validator/contract/TomoValidator.sol @@ -98,7 +98,7 @@ contract TomoValidator { maxValidatorNumber = _maxValidatorNumber; candidateWithdrawDelay = _candidateWithdrawDelay; voterWithdrawDelay = _voterWithdrawDelay; - candidateCount = candidateCount.add(_candidates.length); + candidateCount = _candidates.length; for (uint256 i = 0; i < _candidates.length; i++) { candidates.push(_candidates[i]); @@ -108,7 +108,7 @@ contract TomoValidator { cap: _caps[i] }); voters[_candidates[i]].push(_firstOwner); - validatorsState[candidates[i]].voters[_firstOwner] = minCandidateCap; + validatorsState[_candidates[i]].voters[_firstOwner] = minCandidateCap; } } @@ -120,7 +120,7 @@ contract TomoValidator { isCandidate: true, cap: cap }); - validatorsState[_candidate].voters[msg.sender] = msg.value; + validatorsState[_candidate].voters[msg.sender] = validatorsState[_candidate].voters[msg.sender].add(msg.value); candidateCount = candidateCount.add(1); voters[_candidate].push(msg.sender); emit Propose(msg.sender, _candidate, msg.value); diff --git a/contracts/validator/contract/validator.go b/contracts/validator/contract/validator.go index 69795cf2ed..3947dd3aab 100644 --- a/contracts/validator/contract/validator.go +++ b/contracts/validator/contract/validator.go @@ -180,7 +180,7 @@ func (_SafeMath *SafeMathTransactorRaw) Transact(opts *bind.TransactOpts, method const TomoValidatorABI = "[{\"constant\":false,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"propose\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"},{\"name\":\"_cap\",\"type\":\"uint256\"}],\"name\":\"unvote\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCandidates\",\"outputs\":[{\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_blockNumber\",\"type\":\"uint256\"}],\"name\":\"getWithdrawCap\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"getVoters\",\"outputs\":[{\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getWithdrawBlockNumbers\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"},{\"name\":\"_voter\",\"type\":\"address\"}],\"name\":\"getVoterCap\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"candidates\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_blockNumber\",\"type\":\"uint256\"},{\"name\":\"_index\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"getCandidateCap\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"vote\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"candidateCount\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"voterWithdrawDelay\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"resign\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"getCandidateOwner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxValidatorNumber\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"candidateWithdrawDelay\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"isCandidate\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"minCandidateCap\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"minVoterCap\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_candidates\",\"type\":\"address[]\"},{\"name\":\"_caps\",\"type\":\"uint256[]\"},{\"name\":\"_firstOwner\",\"type\":\"address\"},{\"name\":\"_minCandidateCap\",\"type\":\"uint256\"},{\"name\":\"_minVoterCap\",\"type\":\"uint256\"},{\"name\":\"_maxValidatorNumber\",\"type\":\"uint256\"},{\"name\":\"_candidateWithdrawDelay\",\"type\":\"uint256\"},{\"name\":\"_voterWithdrawDelay\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_voter\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_candidate\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_cap\",\"type\":\"uint256\"}],\"name\":\"Vote\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_voter\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_candidate\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_cap\",\"type\":\"uint256\"}],\"name\":\"Unvote\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_candidate\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_cap\",\"type\":\"uint256\"}],\"name\":\"Propose\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_candidate\",\"type\":\"address\"}],\"name\":\"Resign\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_blockNumber\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"_cap\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"}]" // TomoValidatorBin is the compiled bytecode used for deploying new contracts. -const TomoValidatorBin = `0x6060604052600060045534156200001557600080fd5b6040516200140e3803806200140e833981016040528080518201919060200180518201919060200180519190602001805191906020018051919060200180519190602001805191906020018051600587905560068690556007859055600884905560098190559150600090506200009f8951600454906401000000006200103e620002ac82021704565b6004555060005b88518110156200029d576003805460018101620000c48382620002c3565b916000526020600020900160008b8481518110620000de57fe5b90602001906020020151909190916101000a815481600160a060020a030219169083600160a060020a031602179055505060606040519081016040908152600160a060020a03891682526001602083015281018983815181106200013e57fe5b906020019060200201519052600160008b84815181106200015b57fe5b90602001906020020151600160a060020a03168152602081019190915260400160002081518154600160a060020a031916600160a060020a039190911617815560208201518154901515740100000000000000000000000000000000000000000260a060020a60ff0219909116178155604082015160019091015550600260008a8381518110620001e857fe5b90602001906020020151600160a060020a0316815260208101919091526040016000208054600181016200021d8382620002c3565b50600091825260208220018054600160a060020a031916600160a060020a038a16179055600554600380549192600192909190859081106200025b57fe5b6000918252602080832090910154600160a060020a0390811684528382019490945260409283018220938c1682526002909301909252902055600101620000a6565b50505050505050505062000313565b600082820183811015620002bc57fe5b9392505050565b815481835581811511620002ea57600083815260209020620002ea918101908301620002ef565b505050565b6200031091905b808211156200030c5760008155600101620002f6565b5090565b90565b6110eb80620003236000396000f3006060604052600436106101115763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166301267951811461011657806302aa9be21461012c57806306a49fce1461014e57806315febd68146101b45780632d15cc04146101dc5780632f9c4bba146101fb578063302b68721461020e5780633477ee2e14610233578063441a3e701461026557806358e7525f1461027e5780636dd7d8ea1461029d578063a9a981a3146102b1578063a9ff959e146102c4578063ae6e43f5146102d7578063b642facd146102f6578063d09f1ab414610315578063d161c76714610328578063d51b9e931461033b578063d55b7dff1461036e578063f8ac9dd514610381575b600080fd5b61012a600160a060020a0360043516610394565b005b341561013757600080fd5b61012a600160a060020a03600435166024356105d7565b341561015957600080fd5b61016161080a565b60405160208082528190810183818151815260200191508051906020019060200280838360005b838110156101a0578082015183820152602001610188565b505050509050019250505060405180910390f35b34156101bf57600080fd5b6101ca600435610873565b60405190815260200160405180910390f35b34156101e757600080fd5b610161600160a060020a0360043516610897565b341561020657600080fd5b610161610924565b341561021957600080fd5b6101ca600160a060020a03600435811690602435166109a6565b341561023e57600080fd5b6102496004356109d5565b604051600160a060020a03909116815260200160405180910390f35b341561027057600080fd5b61012a6004356024356109fd565b341561028957600080fd5b6101ca600160a060020a0360043516610b64565b61012a600160a060020a0360043516610b83565b34156102bc57600080fd5b6101ca610d40565b34156102cf57600080fd5b6101ca610d46565b34156102e257600080fd5b61012a600160a060020a0360043516610d4c565b341561030157600080fd5b610249600160a060020a0360043516610fe3565b341561032057600080fd5b6101ca611001565b341561033357600080fd5b6101ca611007565b341561034657600080fd5b61035a600160a060020a036004351661100d565b604051901515815260200160405180910390f35b341561037957600080fd5b6101ca611032565b341561038c57600080fd5b6101ca611038565b6005546000903410156103a657600080fd5b600160a060020a038216600090815260016020526040902054829060a060020a900460ff16156103d557600080fd5b600160a060020a03831660009081526001602081905260409091200154610402903463ffffffff61103e16565b9150600380548060010182816104189190611066565b506000918252602090912001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03851617905560606040519081016040908152600160a060020a0333811683526001602080850182905283850187905291871660009081529152208151815473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03919091161781556020820151815490151560a060020a0274ff0000000000000000000000000000000000000000199091161781556040820151600191820155600160a060020a03808616600090815260208381526040808320339094168352600290930190522034905560045461052092509063ffffffff61103e16565b600455600160a060020a038316600090815260026020526040902080546001810161054b8382611066565b506000918252602090912001805473ffffffffffffffffffffffffffffffffffffffff191633600160a060020a038116919091179091557f7635f1d87b47fba9f2b09e56eb4be75cca030e0cb179c1602ac9261d39a8f5c1908434604051600160a060020a039384168152919092166020820152604080820192909252606001905180910390a1505050565b600160a060020a0380831660009081526001602090815260408083203390941683526002909301905290812054839083908190101561061557600080fd5b600160a060020a038281166000908152600160205260409020543382169116141561068357600554600160a060020a038084166000908152600160209081526040808320339094168352600290930190522054610678908363ffffffff61105416565b101561068357600080fd5b600160a060020a038516600090815260016020819052604090912001546106b0908563ffffffff61105416565b600160a060020a0380871660009081526001602081815260408084209283019590955533909316825260020190915220546106f1908563ffffffff61105416565b600160a060020a03808716600090815260016020908152604080832033909416835260029093019052205560095461072f904363ffffffff61103e16565b600160a060020a033316600090815260208181526040808320848452909152902054909350610764908563ffffffff61103e16565b600160a060020a03331660008181526020818152604080832088845280835290832094909455918152905260019081018054909181016107a48382611066565b5060009182526020909120018390557faa0e554f781c3c3b2be110a0557f260f11af9a8aa2c64bc1e7a31dbb21e32fa2338686604051600160a060020a039384168152919092166020820152604080820192909252606001905180910390a15050505050565b61081261108f565b600380548060200260200160405190810160405280929190818152602001828054801561086857602002820191906000526020600020905b8154600160a060020a0316815260019091019060200180831161084a575b505050505090505b90565b33600160a060020a0316600090815260208181526040808320938352929052205490565b61089f61108f565b6002600083600160a060020a0316600160a060020a0316815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561091857602002820191906000526020600020905b8154600160a060020a031681526001909101906020018083116108fa575b50505050509050919050565b61092c61108f565b60008033600160a060020a0316600160a060020a0316815260200190815260200160002060010180548060200260200160405190810160405280929190818152602001828054801561086857602002820191906000526020600020905b815481526020019060010190808311610989575050505050905090565b600160a060020a0391821660009081526001602090815260408083209390941682526002909201909152205490565b60038054829081106109e357fe5b600091825260209091200154600160a060020a0316905081565b60008282828211610a0d57600080fd5b4382901015610a1b57600080fd5b600160a060020a03331660009081526020818152604080832085845290915281205411610a4757600080fd5b600160a060020a0333166000908152602081905260409020600101805483919083908110610a7157fe5b60009182526020909120015414610a8757600080fd5b600160a060020a03331660008181526020818152604080832089845280835290832080549084905593835291905260010180549194509085908110610ac857fe5b6000918252602082200155600160a060020a03331683156108fc0284604051600060405180830381858888f193505050501515610b0457600080fd5b7ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b5683386856040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390a15050505050565b600160a060020a03166000908152600160208190526040909120015490565b600654341015610b9257600080fd5b600160a060020a038116600090815260016020526040902054819060a060020a900460ff161515610bc257600080fd5b600160a060020a03821660009081526001602081905260409091200154610bef903463ffffffff61103e16565b600160a060020a0380841660009081526001602081815260408084209283019590955533909316825260020190915220541515610c8157600160a060020a0382166000908152600260205260409020805460018101610c4e8382611066565b506000918252602090912001805473ffffffffffffffffffffffffffffffffffffffff191633600160a060020a03161790555b600160a060020a038083166000908152600160209081526040808320339094168352600290930190522054610cbc903463ffffffff61103e16565b600160a060020a03808416600090815260016020908152604080832033948516845260020190915290819020929092557f66a9138482c99e9baf08860110ef332cc0c23b4a199a53593d8db0fc8f96fbfc918490349051600160a060020a039384168152919092166020820152604080820192909252606001905180910390a15050565b60045481565b60095481565b600160a060020a038181166000908152600160205260408120549091829182918591338216911614610d7d57600080fd5b600160a060020a038516600090815260016020526040902054859060a060020a900460ff161515610dad57600080fd5b600160a060020a0386166000908152600160208190526040909120805474ff000000000000000000000000000000000000000019169055600454610df69163ffffffff61105416565b600455600094505b600354851015610e805785600160a060020a0316600386815481101515610e2157fe5b600091825260209091200154600160a060020a03161415610e75576003805486908110610e4a57fe5b6000918252602090912001805473ffffffffffffffffffffffffffffffffffffffff19169055610e80565b600190940193610dfe565b600160a060020a03808716600081815260016020818152604080842033909616845260028601825283205493909252908190529190910154909450610ecb908563ffffffff61105416565b600160a060020a0380881660009081526001602081815260408084209283019590955533909316825260020190915290812055600854610f11904363ffffffff61103e16565b600160a060020a033316600090815260208181526040808320848452909152902054909350610f46908563ffffffff61103e16565b600160a060020a0333166000818152602081815260408083208884528083529083209490945591815290526001908101805490918101610f868382611066565b5060009182526020909120018390557f4edf3e325d0063213a39f9085522994a1c44bea5f39e7d63ef61260a1e58c6d33387604051600160a060020a039283168152911660208201526040908101905180910390a1505050505050565b600160a060020a039081166000908152600160205260409020541690565b60075481565b60085481565b600160a060020a031660009081526001602052604090205460a060020a900460ff1690565b60055481565b60065481565b60008282018381101561104d57fe5b9392505050565b60008282111561106057fe5b50900390565b81548183558181151161108a5760008381526020902061108a9181019083016110a1565b505050565b60206040519081016040526000815290565b61087091905b808211156110bb57600081556001016110a7565b50905600a165627a7a7230582006ba34ba8a7d4cae8607d3da715fc79d484fd7cb6dd98b06d820244296874eba0029` +const TomoValidatorBin = `0x6060604052600060045534156200001557600080fd5b60405162001415380380620014158339810160405280805182019190602001805182019190602001805191906020018051919060200180519190602001805191906020018051919060200180516005879055600686905560078590556008849055600981905591506000905088516004555060005b88518110156200027c576003805460018101620000a883826200028b565b916000526020600020900160008b8481518110620000c257fe5b90602001906020020151909190916101000a815481600160a060020a030219169083600160a060020a031602179055505060606040519081016040908152600160a060020a03891682526001602083015281018983815181106200012257fe5b906020019060200201519052600160008b84815181106200013f57fe5b90602001906020020151600160a060020a03168152602081019190915260400160002081518154600160a060020a031916600160a060020a039190911617815560208201518154901515740100000000000000000000000000000000000000000260a060020a60ff0219909116178155604082015160019091015550600260008a8381518110620001cc57fe5b90602001906020020151600160a060020a0316815260208101919091526040016000208054600181016200020183826200028b565b50600091825260208220018054600160a060020a031916600160a060020a038a16179055600554906001908b84815181106200023957fe5b90602001906020020151600160a060020a03908116825260208083019390935260409182016000908120918c16815260029091019092529020556001016200008a565b505050505050505050620002db565b815481835581811511620002b257600083815260209020620002b2918101908301620002b7565b505050565b620002d891905b80821115620002d45760008155600101620002be565b5090565b90565b61112a80620002eb6000396000f3006060604052600436106101115763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166301267951811461011657806302aa9be21461012c57806306a49fce1461014e57806315febd68146101b45780632d15cc04146101dc5780632f9c4bba146101fb578063302b68721461020e5780633477ee2e14610233578063441a3e701461026557806358e7525f1461027e5780636dd7d8ea1461029d578063a9a981a3146102b1578063a9ff959e146102c4578063ae6e43f5146102d7578063b642facd146102f6578063d09f1ab414610315578063d161c76714610328578063d51b9e931461033b578063d55b7dff1461036e578063f8ac9dd514610381575b600080fd5b61012a600160a060020a0360043516610394565b005b341561013757600080fd5b61012a600160a060020a0360043516602435610616565b341561015957600080fd5b610161610849565b60405160208082528190810183818151815260200191508051906020019060200280838360005b838110156101a0578082015183820152602001610188565b505050509050019250505060405180910390f35b34156101bf57600080fd5b6101ca6004356108b2565b60405190815260200160405180910390f35b34156101e757600080fd5b610161600160a060020a03600435166108d6565b341561020657600080fd5b610161610963565b341561021957600080fd5b6101ca600160a060020a03600435811690602435166109e5565b341561023e57600080fd5b610249600435610a14565b604051600160a060020a03909116815260200160405180910390f35b341561027057600080fd5b61012a600435602435610a3c565b341561028957600080fd5b6101ca600160a060020a0360043516610ba3565b61012a600160a060020a0360043516610bc2565b34156102bc57600080fd5b6101ca610d7f565b34156102cf57600080fd5b6101ca610d85565b34156102e257600080fd5b61012a600160a060020a0360043516610d8b565b341561030157600080fd5b610249600160a060020a0360043516611022565b341561032057600080fd5b6101ca611040565b341561033357600080fd5b6101ca611046565b341561034657600080fd5b61035a600160a060020a036004351661104c565b604051901515815260200160405180910390f35b341561037957600080fd5b6101ca611071565b341561038c57600080fd5b6101ca611077565b6005546000903410156103a657600080fd5b600160a060020a038216600090815260016020526040902054829060a060020a900460ff16156103d557600080fd5b600160a060020a03831660009081526001602081905260409091200154610402903463ffffffff61107d16565b91506003805480600101828161041891906110a5565b506000918252602090912001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03851617905560606040519081016040908152600160a060020a0333811683526001602080850182905283850187905291871660009081529152208151815473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03919091161781556020820151815490151560a060020a0274ff0000000000000000000000000000000000000000199091161781556040820151600191820155600160a060020a03808616600090815260209283526040808220339093168252600290920190925290205461051d91503463ffffffff61107d16565b600160a060020a038085166000908152600160208181526040808420339095168452600290940190529190209190915560045461055f9163ffffffff61107d16565b600455600160a060020a038316600090815260026020526040902080546001810161058a83826110a5565b506000918252602090912001805473ffffffffffffffffffffffffffffffffffffffff191633600160a060020a038116919091179091557f7635f1d87b47fba9f2b09e56eb4be75cca030e0cb179c1602ac9261d39a8f5c1908434604051600160a060020a039384168152919092166020820152604080820192909252606001905180910390a1505050565b600160a060020a0380831660009081526001602090815260408083203390941683526002909301905290812054839083908190101561065457600080fd5b600160a060020a03828116600090815260016020526040902054338216911614156106c257600554600160a060020a0380841660009081526001602090815260408083203390941683526002909301905220546106b7908363ffffffff61109316565b10156106c257600080fd5b600160a060020a038516600090815260016020819052604090912001546106ef908563ffffffff61109316565b600160a060020a038087166000908152600160208181526040808420928301959095553390931682526002019091522054610730908563ffffffff61109316565b600160a060020a03808716600090815260016020908152604080832033909416835260029093019052205560095461076e904363ffffffff61107d16565b600160a060020a0333166000908152602081815260408083208484529091529020549093506107a3908563ffffffff61107d16565b600160a060020a03331660008181526020818152604080832088845280835290832094909455918152905260019081018054909181016107e383826110a5565b5060009182526020909120018390557faa0e554f781c3c3b2be110a0557f260f11af9a8aa2c64bc1e7a31dbb21e32fa2338686604051600160a060020a039384168152919092166020820152604080820192909252606001905180910390a15050505050565b6108516110ce565b60038054806020026020016040519081016040528092919081815260200182805480156108a757602002820191906000526020600020905b8154600160a060020a03168152600190910190602001808311610889575b505050505090505b90565b33600160a060020a0316600090815260208181526040808320938352929052205490565b6108de6110ce565b6002600083600160a060020a0316600160a060020a0316815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561095757602002820191906000526020600020905b8154600160a060020a03168152600190910190602001808311610939575b50505050509050919050565b61096b6110ce565b60008033600160a060020a0316600160a060020a031681526020019081526020016000206001018054806020026020016040519081016040528092919081815260200182805480156108a757602002820191906000526020600020905b8154815260200190600101908083116109c8575050505050905090565b600160a060020a0391821660009081526001602090815260408083209390941682526002909201909152205490565b6003805482908110610a2257fe5b600091825260209091200154600160a060020a0316905081565b60008282828211610a4c57600080fd5b4382901015610a5a57600080fd5b600160a060020a03331660009081526020818152604080832085845290915281205411610a8657600080fd5b600160a060020a0333166000908152602081905260409020600101805483919083908110610ab057fe5b60009182526020909120015414610ac657600080fd5b600160a060020a03331660008181526020818152604080832089845280835290832080549084905593835291905260010180549194509085908110610b0757fe5b6000918252602082200155600160a060020a03331683156108fc0284604051600060405180830381858888f193505050501515610b4357600080fd5b7ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b5683386856040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390a15050505050565b600160a060020a03166000908152600160208190526040909120015490565b600654341015610bd157600080fd5b600160a060020a038116600090815260016020526040902054819060a060020a900460ff161515610c0157600080fd5b600160a060020a03821660009081526001602081905260409091200154610c2e903463ffffffff61107d16565b600160a060020a0380841660009081526001602081815260408084209283019590955533909316825260020190915220541515610cc057600160a060020a0382166000908152600260205260409020805460018101610c8d83826110a5565b506000918252602090912001805473ffffffffffffffffffffffffffffffffffffffff191633600160a060020a03161790555b600160a060020a038083166000908152600160209081526040808320339094168352600290930190522054610cfb903463ffffffff61107d16565b600160a060020a03808416600090815260016020908152604080832033948516845260020190915290819020929092557f66a9138482c99e9baf08860110ef332cc0c23b4a199a53593d8db0fc8f96fbfc918490349051600160a060020a039384168152919092166020820152604080820192909252606001905180910390a15050565b60045481565b60095481565b600160a060020a038181166000908152600160205260408120549091829182918591338216911614610dbc57600080fd5b600160a060020a038516600090815260016020526040902054859060a060020a900460ff161515610dec57600080fd5b600160a060020a0386166000908152600160208190526040909120805474ff000000000000000000000000000000000000000019169055600454610e359163ffffffff61109316565b600455600094505b600354851015610ebf5785600160a060020a0316600386815481101515610e6057fe5b600091825260209091200154600160a060020a03161415610eb4576003805486908110610e8957fe5b6000918252602090912001805473ffffffffffffffffffffffffffffffffffffffff19169055610ebf565b600190940193610e3d565b600160a060020a03808716600081815260016020818152604080842033909616845260028601825283205493909252908190529190910154909450610f0a908563ffffffff61109316565b600160a060020a0380881660009081526001602081815260408084209283019590955533909316825260020190915290812055600854610f50904363ffffffff61107d16565b600160a060020a033316600090815260208181526040808320848452909152902054909350610f85908563ffffffff61107d16565b600160a060020a0333166000818152602081815260408083208884528083529083209490945591815290526001908101805490918101610fc583826110a5565b5060009182526020909120018390557f4edf3e325d0063213a39f9085522994a1c44bea5f39e7d63ef61260a1e58c6d33387604051600160a060020a039283168152911660208201526040908101905180910390a1505050505050565b600160a060020a039081166000908152600160205260409020541690565b60075481565b60085481565b600160a060020a031660009081526001602052604090205460a060020a900460ff1690565b60055481565b60065481565b60008282018381101561108c57fe5b9392505050565b60008282111561109f57fe5b50900390565b8154818355818115116110c9576000838152602090206110c99181019083016110e0565b505050565b60206040519081016040526000815290565b6108af91905b808211156110fa57600081556001016110e6565b50905600a165627a7a72305820555de7c5131842a4fccb258fccd95ae1539019bb744b4253893b37fed1b3d8e90029` // DeployTomoValidator deploys a new Ethereum contract, binding an instance of TomoValidator to it. func DeployTomoValidator(auth *bind.TransactOpts, backend bind.ContractBackend, _candidates []common.Address, _caps []*big.Int, _firstOwner common.Address, _minCandidateCap *big.Int, _minVoterCap *big.Int, _maxValidatorNumber *big.Int, _candidateWithdrawDelay *big.Int, _voterWithdrawDelay *big.Int) (common.Address, *types.Transaction, *TomoValidator, error) { diff --git a/core/blockchain.go b/core/blockchain.go index 80b3bc1307..e68f0bdedd 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -75,6 +75,13 @@ type CacheConfig struct { TrieNodeLimit int // Memory limit (MB) at which to flush the current in-memory trie to disk TrieTimeLimit time.Duration // Time limit after which to flush the current in-memory trie to disk } +type ResultProcessBlock struct { + logs []*types.Log + receipts []*types.Receipt + state *state.StateDB + proctime time.Duration + usedGas uint64 +} // BlockChain represents the canonical chain given a database with a genesis // block. The Blockchain manages chain imports, reverts, chain reorganisations. @@ -115,14 +122,16 @@ type BlockChain struct { currentBlock atomic.Value // Current head of the block chain currentFastBlock atomic.Value // Current head of the fast-sync chain (may be above the block chain!) - stateCache state.Database // State database to reuse between imports (contains state cache) - bodyCache *lru.Cache // Cache for the most recent block bodies - bodyRLPCache *lru.Cache // Cache for the most recent block bodies in RLP encoded format - blockCache *lru.Cache // Cache for the most recent entire blocks - futureBlocks *lru.Cache // future blocks are blocks added for later processing - - quit chan struct{} // blockchain quit channel - running int32 // running must be called atomically + stateCache state.Database // State database to reuse between imports (contains state cache) + bodyCache *lru.Cache // Cache for the most recent block bodies + bodyRLPCache *lru.Cache // Cache for the most recent block bodies in RLP encoded format + blockCache *lru.Cache // Cache for the most recent entire blocks + futureBlocks *lru.Cache // future blocks are blocks added for later processing + resultProcess *lru.Cache // Cache for processed blocks + calculatingBlock *lru.Cache // Cache for processing blocks + downloadingBlock *lru.Cache // Cache for downloading blocks (avoid duplication from fetcher) + quit chan struct{} // blockchain quit channel + running int32 // running must be called atomically // procInterrupt must be atomically called procInterrupt int32 // interrupt signaler for block processing wg sync.WaitGroup // chain processing wait group for shutting down @@ -152,21 +161,26 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par blockCache, _ := lru.New(blockCacheLimit) futureBlocks, _ := lru.New(maxFutureBlocks) badBlocks, _ := lru.New(badBlockLimit) - + resultProcess, _ := lru.New(blockCacheLimit) + preparingBlock, _ := lru.New(blockCacheLimit) + downloadingBlock, _ := lru.New(blockCacheLimit) bc := &BlockChain{ - chainConfig: chainConfig, - cacheConfig: cacheConfig, - db: db, - triegc: prque.New(), - stateCache: state.NewDatabase(db), - quit: make(chan struct{}), - bodyCache: bodyCache, - bodyRLPCache: bodyRLPCache, - blockCache: blockCache, - futureBlocks: futureBlocks, - engine: engine, - vmConfig: vmConfig, - badBlocks: badBlocks, + chainConfig: chainConfig, + cacheConfig: cacheConfig, + db: db, + triegc: prque.New(), + stateCache: state.NewDatabase(db), + quit: make(chan struct{}), + bodyCache: bodyCache, + bodyRLPCache: bodyRLPCache, + blockCache: blockCache, + futureBlocks: futureBlocks, + resultProcess: resultProcess, + calculatingBlock: preparingBlock, + downloadingBlock: downloadingBlock, + engine: engine, + vmConfig: vmConfig, + badBlocks: badBlocks, } bc.SetValidator(NewBlockValidator(chainConfig, bc, engine)) bc.SetProcessor(NewStateProcessor(chainConfig, bc, engine)) @@ -892,7 +906,7 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types. defer bc.mu.Unlock() currentBlock := bc.CurrentBlock() - //localTd := bc.GetTd(currentBlock.Hash(), currentBlock.NumberU64()) + localTd := bc.GetTd(currentBlock.Hash(), currentBlock.NumberU64()) externTd := new(big.Int).Add(block.Difficulty(), ptd) // Irrelevant of the canonical status, write the block itself to the database @@ -966,8 +980,12 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types. // If the total difficulty is higher than our known, add it to the canonical chain // Second clause in the if statement reduces the vulnerability to selfish mining. // Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf - - reorg := block.NumberU64() > currentBlock.NumberU64() + reorg := externTd.Cmp(localTd) > 0 + currentBlock = bc.CurrentBlock() + if !reorg && externTd.Cmp(localTd) == 0 { + // Split same-difficulty blocks by number + reorg = block.NumberU64() > currentBlock.NumberU64() + } if reorg { // Reorganise the chain if the parent is not the head block if block.ParentHash() != currentBlock.Hash() { @@ -1049,6 +1067,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks) (int, []interface{}, []*ty for i, block := range chain { headers[i] = block.Header() seals[i] = true + bc.downloadingBlock.Add(block.Hash(), true) } abort, results := bc.engine.VerifyHeaders(bc, headers, seals) defer close(abort) @@ -1168,7 +1187,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks) (int, []interface{}, []*ty } switch status { case CanonStatTy: - log.Debug("Inserted new block", "number", block.Number(), "hash", block.Hash(), "uncles", len(block.Uncles()), + log.Debug("Inserted new block from downloader", "number", block.Number(), "hash", block.Hash(), "uncles", len(block.Uncles()), "txs", len(block.Transactions()), "gas", block.GasUsed(), "elapsed", common.PrettyDuration(time.Since(bstart))) coalescedLogs = append(coalescedLogs, logs...) @@ -1180,7 +1199,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks) (int, []interface{}, []*ty bc.gcproc += proctime case SideStatTy: - log.Debug("Inserted forked block", "number", block.Number(), "hash", block.Hash(), "diff", block.Difficulty(), "elapsed", + log.Debug("Inserted forked block from downloader", "number", block.Number(), "hash", block.Hash(), "diff", block.Difficulty(), "elapsed", common.PrettyDuration(time.Since(bstart)), "txs", len(block.Transactions()), "gas", block.GasUsed(), "uncles", len(block.Uncles())) blockInsertTimer.UpdateSince(bstart) @@ -1189,7 +1208,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks) (int, []interface{}, []*ty stats.processed++ stats.usedGas += usedGas stats.report(chain, i, bc.stateCache.TrieDB().Size()) - if bc.chainConfig.Posv != nil { + if status == CanonStatTy && bc.chainConfig.Posv != nil { // epoch block if (chain[i].NumberU64() % bc.chainConfig.Posv.Epoch) == 0 { CheckpointCh <- 1 @@ -1206,11 +1225,212 @@ func (bc *BlockChain) insertChain(chain types.Blocks) (int, []interface{}, []*ty } // Append a single chain head event if we've progressed the chain if lastCanon != nil && bc.CurrentBlock().Hash() == lastCanon.Hash() { + log.Debug("New ChainHeadEvent ", "number", lastCanon.NumberU64(), "hash", lastCanon.Hash()) events = append(events, ChainHeadEvent{lastCanon}) } return 0, events, coalescedLogs, nil } +func (bc *BlockChain) InsertBlock(block *types.Block) error { + events, logs, err := bc.insertBlock(block) + bc.PostChainEvents(events, logs) + return err +} + +func (bc *BlockChain) PrepareBlock(block *types.Block) (err error) { + defer log.Debug("Done prepare block ", "number", block.NumberU64(), "hash", block.Hash(), "validator", block.Header().Validator, "err", err) + if _, check := bc.resultProcess.Get(block.Hash()); check { + log.Debug("Stop prepare a block because the result cached", "number", block.NumberU64(), "hash", block.Hash(), "validator", block.Header().Validator) + return nil + } + if _, check := bc.calculatingBlock.Get(block.Hash()); check { + log.Debug("Stop prepare a block because inserting", "number", block.NumberU64(), "hash", block.Hash(), "validator", block.Header().Validator) + return nil + } + err = bc.engine.VerifyHeader(bc, block.Header(), false) + if err != nil { + return err + } + result, err := bc.getResultBlock(block, false) + if err == nil { + bc.resultProcess.Add(block.Hash(), result) + return nil + } else if err == ErrKnownBlock { + return nil + } else if err == ErrStopPreparingBlock { + log.Debug("Stop prepare a block because calculating", "number", block.NumberU64(), "hash", block.Hash(), "validator", block.Header().Validator) + return nil + } + return err +} + +func (bc *BlockChain) getResultBlock(block *types.Block, verifiedM2 bool) (*ResultProcessBlock, error) { + var calculatedBlock *CalculatedBlock + if verifiedM2 { + if result, check := bc.resultProcess.Get(block.HashNoValidator()); check { + log.Debug("Get result block from cache ", "number", block.NumberU64(), "hash", block.Hash(), "hash no validator", block.HashNoValidator()) + return result.(*ResultProcessBlock), nil + } + log.Debug("Not found cache prepare block ", "number", block.NumberU64(), "hash", block.Hash(), "validator", block.HashNoValidator()) + if calculatedBlock, _ := bc.calculatingBlock.Get(block.HashNoValidator()); calculatedBlock != nil { + calculatedBlock.(*CalculatedBlock).stop = true + } + } + calculatedBlock = &CalculatedBlock{block, false} + bc.calculatingBlock.Add(block.HashNoValidator(), calculatedBlock) + // Start the parallel header verifier + // If the chain is terminating, stop processing blocks + if atomic.LoadInt32(&bc.procInterrupt) == 1 { + log.Debug("Premature abort during blocks processing") + return nil, ErrBlacklistedHash + } + // If the header is a banned one, straight out abort + if BadHashes[block.Hash()] { + bc.reportBlock(block, nil, ErrBlacklistedHash) + return nil, ErrBlacklistedHash + } + // Wait for the block's verification to complete + bstart := time.Now() + err := bc.Validator().ValidateBody(block) + switch { + case err == ErrKnownBlock: + // Block and state both already known. However if the current block is below + // this number we did a rollback and we should reimport it nonetheless. + if bc.CurrentBlock().NumberU64() >= block.NumberU64() { + return nil, ErrKnownBlock + } + case err == consensus.ErrPrunedAncestor: + // Block competing with the canonical chain, store in the db, but don't process + // until the competitor TD goes above the canonical TD + currentBlock := bc.CurrentBlock() + localTd := bc.GetTd(currentBlock.Hash(), currentBlock.NumberU64()) + externTd := new(big.Int).Add(bc.GetTd(block.ParentHash(), block.NumberU64()-1), block.Difficulty()) + if localTd.Cmp(externTd) > 0 { + return nil, err + } + // Competitor chain beat canonical, gather all blocks from the common ancestor + var winner []*types.Block + + parent := bc.GetBlock(block.ParentHash(), block.NumberU64()-1) + for !bc.HasState(parent.Root()) { + winner = append(winner, parent) + parent = bc.GetBlock(parent.ParentHash(), parent.NumberU64()-1) + } + for j := 0; j < len(winner)/2; j++ { + winner[j], winner[len(winner)-1-j] = winner[len(winner)-1-j], winner[j] + } + log.Debug("Number block need calculated again", "number", block.NumberU64(), "hash", block.Hash().Hex(), "winners", len(winner)) + // Import all the pruned blocks to make the state available + _, _, _, err := bc.insertChain(winner) + if err != nil { + return nil, err + } + case err != nil: + bc.reportBlock(block, nil, err) + return nil, err + } + // Create a new statedb using the parent block and report an + // error if it fails. + var parent = bc.GetBlock(block.ParentHash(), block.NumberU64()-1) + state, err := state.New(parent.Root(), bc.stateCache) + if err != nil { + return nil, err + } + // Process block using the parent state as reference point. + receipts, logs, usedGas, err := bc.processor.ProcessBlockNoValidator(calculatedBlock, state, bc.vmConfig) + process := time.Since(bstart) + if err != nil { + if err != ErrStopPreparingBlock { + bc.reportBlock(block, receipts, err) + } + return nil, err + } + // Validate the state using the default validator + err = bc.Validator().ValidateState(block, parent, state, receipts, usedGas) + if err != nil { + bc.reportBlock(block, receipts, err) + return nil, err + } + proctime := time.Since(bstart) + log.Debug("Calculate new block", "number", block.Number(), "hash", block.Hash(), "uncles", len(block.Uncles()), + "txs", len(block.Transactions()), "gas", block.GasUsed(), "elapsed", common.PrettyDuration(time.Since(bstart)), "process", process) + return &ResultProcessBlock{receipts: receipts, logs: logs, state: state, proctime: proctime, usedGas: usedGas}, nil +} + +// insertChain will execute the actual chain insertion and event aggregation. The +// only reason this method exists as a separate one is to make locking cleaner +// with deferred statements. +func (bc *BlockChain) insertBlock(block *types.Block) ([]interface{}, []*types.Log, error) { + var ( + stats = insertStats{startTime: mclock.Now()} + events = make([]interface{}, 0, 1) + coalescedLogs []*types.Log + ) + if _, check := bc.downloadingBlock.Get(block.Hash()); check { + log.Debug("Stop fetcher a block because downloading", "number", block.NumberU64(), "hash", block.Hash()) + return events, coalescedLogs, nil + } + result, err := bc.getResultBlock(block, true) + if err != nil { + return events, coalescedLogs, err + } + defer bc.resultProcess.Remove(block.HashNoValidator()) + bc.wg.Add(1) + defer bc.wg.Done() + // Write the block to the chain and get the status. + bc.chainmu.Lock() + defer bc.chainmu.Unlock() + if bc.HasBlockAndState(block.Hash(), block.NumberU64()) { + return events, coalescedLogs, nil + } + status, err := bc.WriteBlockWithState(block, result.receipts, result.state) + + if err != nil { + return events, coalescedLogs, err + } + switch status { + case CanonStatTy: + log.Debug("Inserted new block from fetcher", "number", block.Number(), "hash", block.Hash(), "uncles", len(block.Uncles()), + "txs", len(block.Transactions()), "gas", block.GasUsed(), "elapsed", common.PrettyDuration(time.Since(block.ReceivedAt))) + + coalescedLogs = append(coalescedLogs, result.logs...) + events = append(events, ChainEvent{block, block.Hash(), result.logs}) + + // Only count canonical blocks for GC processing time + bc.gcproc += result.proctime + + case SideStatTy: + log.Debug("Inserted forked block from fetcher", "number", block.Number(), "hash", block.Hash(), "diff", block.Difficulty(), "elapsed", + common.PrettyDuration(time.Since(block.ReceivedAt)), "txs", len(block.Transactions()), "gas", block.GasUsed(), "uncles", len(block.Uncles())) + + blockInsertTimer.Update(result.proctime) + events = append(events, ChainSideEvent{block}) + } + stats.processed++ + stats.usedGas += result.usedGas + stats.report(types.Blocks{block}, 0, bc.stateCache.TrieDB().Size()) + if status == CanonStatTy && bc.chainConfig.Posv != nil { + // epoch block + if (block.NumberU64() % bc.chainConfig.Posv.Epoch) == 0 { + CheckpointCh <- 1 + } + // prepare set of masternodes for the next epoch + if (block.NumberU64() % bc.chainConfig.Posv.Epoch) == (bc.chainConfig.Posv.Epoch - bc.chainConfig.Posv.Gap) { + err := bc.UpdateM1() + if err != nil { + log.Error("Error when update masternodes set. Stopping node", "err", err) + os.Exit(1) + } + } + } + // Append a single chain head event if we've progressed the chain + if status == CanonStatTy && bc.CurrentBlock().Hash() == block.Hash() { + events = append(events, ChainHeadEvent{block}) + log.Debug("New ChainHeadEvent from fetcher ", "number", block.NumberU64(), "hash", block.Hash()) + } + return events, coalescedLogs, nil +} + // insertStats tracks and reports on block insertion. type insertStats struct { queued, processed, ignored int diff --git a/core/error.go b/core/error.go index 86b093b151..63be6ab83d 100644 --- a/core/error.go +++ b/core/error.go @@ -36,4 +36,6 @@ var ( ErrNotPoSV = errors.New("Posv not found in config") ErrNotFoundM1 = errors.New("list M1 not found ") + + ErrStopPreparingBlock = errors.New("stop calculating a block not verified by M2") ) diff --git a/core/state_processor.go b/core/state_processor.go index 962d4735ad..52d1fc0f65 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -40,6 +40,10 @@ type StateProcessor struct { bc *BlockChain // Canonical block chain engine consensus.Engine // Consensus engine used for block rewards } +type CalculatedBlock struct { + block *types.Block + stop bool +} // NewStateProcessor initialises a new StateProcessor. func NewStateProcessor(config *params.ChainConfig, bc *BlockChain, engine consensus.Engine) *StateProcessor { @@ -69,9 +73,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 { misc.ApplyDAOHardFork(statedb) } - InitSignerInTransactions(p.config, header, block.Transactions()) - // Iterate over and process the individual transactions for i, tx := range block.Transactions() { statedb.Prepare(tx.Hash(), block.Hash(), i) receipt, _, err := ApplyTransaction(p.config, p.bc, nil, gp, statedb, header, tx, usedGas, cfg) @@ -83,7 +85,44 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg } // Finalize the block, applying any consensus engine specific extras (e.g. block rewards) p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles(), receipts) + return receipts, allLogs, *usedGas, nil +} +func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) { + block := cBlock.block + var ( + receipts types.Receipts + usedGas = new(uint64) + header = block.Header() + allLogs []*types.Log + gp = new(GasPool).AddGas(block.GasLimit()) + ) + // Mutate the the block and state according to any hard-fork specs + if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 { + misc.ApplyDAOHardFork(statedb) + } + if cBlock.stop { + return nil, nil, 0, ErrStopPreparingBlock + } + InitSignerInTransactions(p.config, header, block.Transactions()) + if cBlock.stop { + return nil, nil, 0, ErrStopPreparingBlock + } + // Iterate over and process the individual transactions + receipts = make([]*types.Receipt, block.Transactions().Len()) + for i, tx := range block.Transactions() { + statedb.Prepare(tx.Hash(), block.Hash(), i) + receipt, _, err := ApplyTransaction(p.config, p.bc, nil, gp, statedb, header, tx, usedGas, cfg) + if err != nil { + return nil, nil, 0, err + } + if cBlock.stop { + return nil, nil, 0, ErrStopPreparingBlock + } + receipts[i] = receipt + } + // Finalize the block, applying any consensus engine specific extras (e.g. block rewards) + p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles(), receipts) return receipts, allLogs, *usedGas, nil } diff --git a/core/tx_pool.go b/core/tx_pool.go index 8cae8434e4..ec029ed939 100644 --- a/core/tx_pool.go +++ b/core/tx_pool.go @@ -188,17 +188,16 @@ func (config *TxPoolConfig) sanitize() TxPoolConfig { // current state) and future transactions. Transactions move between those // two states over time as they are received and processed. type TxPool struct { - config TxPoolConfig - chainconfig *params.ChainConfig - chain blockChain - gasPrice *big.Int - txFeed event.Feed - specialTxFeed event.Feed - scope event.SubscriptionScope - chainHeadCh chan ChainHeadEvent - chainHeadSub event.Subscription - signer types.Signer - mu sync.RWMutex + config TxPoolConfig + chainconfig *params.ChainConfig + chain blockChain + gasPrice *big.Int + txFeed event.Feed + scope event.SubscriptionScope + chainHeadCh chan ChainHeadEvent + chainHeadSub event.Subscription + signer types.Signer + mu sync.RWMutex currentState *state.StateDB // Current state in the blockchain head pendingState *state.ManagedState // Pending state tracking virtual nonces @@ -458,12 +457,6 @@ func (pool *TxPool) SubscribeTxPreEvent(ch chan<- TxPreEvent) event.Subscription return pool.scope.Track(pool.txFeed.Subscribe(ch)) } -// SubscribeSpecialTxPreEvent registers a subscription of TxPreEvent and -// starts sending event to the given channel. -func (pool *TxPool) SubscribeSpecialTxPreEvent(ch chan<- TxPreEvent) event.Subscription { - return pool.scope.Track(pool.specialTxFeed.Subscribe(ch)) -} - // GasPrice returns the current gas price enforced by the transaction pool. func (pool *TxPool) GasPrice() *big.Int { pool.mu.RLock() @@ -654,11 +647,12 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (bool, error) { return false, err } from, _ := types.Sender(pool.signer, tx) // already validated - if tx.IsSpecialTransaction() && pool.IsMasterNode != nil && pool.IsMasterNode(from) { + if tx.IsSpecialTransaction() && pool.IsMasterNode != nil && pool.IsMasterNode(from) && pool.pendingState.GetNonce(from) == tx.Nonce() { return pool.promoteSpecialTx(from, tx) } // If the transaction pool is full, discard underpriced transactions if uint64(len(pool.all)) >= pool.config.GlobalSlots+pool.config.GlobalQueue { + log.Debug("Add transaction to pool full", "hash", hash, "nonce", tx.Nonce()) // If the new transaction is underpriced, don't accept it if pool.priced.Underpriced(tx, pool.locals) { log.Trace("Discarding underpriced transaction", "hash", hash, "price", tx.GasPrice()) @@ -819,21 +813,7 @@ func (pool *TxPool) promoteSpecialTx(addr common.Address, tx *types.Transaction) // Set the potentially new pending nonce and notify any subsystems of the new tx pool.beats[addr] = time.Now() pool.pendingState.SetNonce(addr, tx.Nonce()+1) - broadcastTxs := types.Transactions{} - for i := tx.Nonce() - 1; i > 0; i-- { - before := list.txs.Get(i) - if before == nil || before.IsSpecialTransaction() { - break - } - broadcastTxs = append(broadcastTxs, before) - } - broadcastTxs = append(broadcastTxs, tx) - go func() { - for _, btx := range broadcastTxs { - pool.specialTxFeed.Send(TxPreEvent{btx}) - log.Trace("Pooled new special transaction", "hash", tx.Hash(), "from", addr, "to", tx.To(), "nonce", tx.Nonce()) - } - }() + go pool.txFeed.Send(TxPreEvent{tx}) return true, nil } @@ -887,9 +867,6 @@ func (pool *TxPool) addTx(tx *types.Transaction, local bool) error { // addTxs attempts to queue a batch of transactions if they are valid. func (pool *TxPool) addTxs(txs []*types.Transaction, local bool) []error { - for _, tx := range txs { - types.CacheSigner(pool.signer, tx) - } pool.mu.Lock() defer pool.mu.Unlock() diff --git a/core/types.go b/core/types.go index d0bbaf0aa7..3f691cb420 100644 --- a/core/types.go +++ b/core/types.go @@ -43,4 +43,5 @@ type Validator interface { // failed. type Processor interface { Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) + ProcessBlockNoValidator(block *CalculatedBlock, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) } diff --git a/core/types/block.go b/core/types/block.go index 25865d4b25..87d989b69c 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -125,6 +125,30 @@ func (h *Header) HashNoNonce() common.Hash { }) } +// HashNoNonce returns the hash which is used as input for the proof-of-work search. +func (h *Header) HashNoValidator() common.Hash { + return rlpHash([]interface{}{ + h.ParentHash, + h.UncleHash, + h.Coinbase, + h.Root, + h.TxHash, + h.ReceiptHash, + h.Bloom, + h.Difficulty, + h.Number, + h.GasLimit, + h.GasUsed, + h.Time, + h.Extra, + h.MixDigest, + h.Nonce, + h.Validators, + []byte{}, + h.Penalties, + }) +} + // Size returns the approximate memory used by all internal contents. It is used // to approximate and limit the memory consumption of various caches. func (h *Header) Size() common.StorageSize { @@ -337,6 +361,9 @@ func (b *Block) Body() *Body { return &Body{b.transactions, b.uncles} } func (b *Block) HashNoNonce() common.Hash { return b.header.HashNoNonce() } +func (b *Block) HashNoValidator() common.Hash { + return b.header.HashNoValidator() +} // Size returns the true RLP encoded storage size of the block, either by encoding // and returning it, or returning a previsouly cached value. diff --git a/core/types/transaction_test.go b/core/types/transaction_test.go index 4e74a0e9b8..6539f69a3f 100644 --- a/core/types/transaction_test.go +++ b/core/types/transaction_test.go @@ -144,7 +144,7 @@ func TestTransactionPriceNonceSort(t *testing.T) { } } // Sort the transactions and cross check the nonce ordering - txset, _ := NewTransactionsByPriceAndNonce(signer, groups,nil) + txset, _ := NewTransactionsByPriceAndNonce(signer, groups, nil) txs := Transactions{} for tx := txset.Peek(); tx != nil; tx = txset.Peek() { diff --git a/docker/tomochain/entrypoint.sh b/docker/tomochain/entrypoint.sh index 6a1ab2e0b9..966154d1fc 100755 --- a/docker/tomochain/entrypoint.sh +++ b/docker/tomochain/entrypoint.sh @@ -28,7 +28,7 @@ accountsCount=$( # file to env for env in IDENTITY PASSWORD PRIVATE_KEY BOOTNODES WS_SECRET NETSTATS_HOST \ - NETSTATS_PORT EXTIP SYNC_MODE NETWORK_ID; do + NETSTATS_PORT EXTIP SYNC_MODE NETWORK_ID ANNOUNCE_TXS; do file=$(eval echo "\$${env}_FILE") if [[ -f $file ]] && [[ ! -z $file ]]; then echo "Replacing $env by $file" @@ -139,6 +139,11 @@ else echo "WS_SECRET not set, will not report to netstats server." fi +# annonce txs +if [[ ! -z $ANNOUNCE_TXS ]]; then + params="$params --announce-txs" +fi + # dump echo "dump: $IDENTITY $account $BOOTNODES" @@ -151,7 +156,7 @@ exec tomo $params \ --identity $IDENTITY \ --password ./password \ --port 30303 \ - --maxpeers 50 \ + --maxpeers 25 \ --txpool.globalqueue 5000 \ --txpool.globalslots 5000 \ --rpc \ diff --git a/eth/backend.go b/eth/backend.go index f3790b99db..3f998e098e 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -173,7 +173,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.SyncMode, config.NetworkId, eth.eventMux, eth.txPool, eth.engine, eth.blockchain, chainDb); err != nil { return nil, err } - eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.engine) + eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.engine, ctx.GetConfig().AnnounceTxs) eth.miner.SetExtra(makeExtraData(config.ExtraData)) eth.ApiBackend = &EthApiBackend{eth, nil} @@ -203,47 +203,43 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { return nil } - appendM2HeaderHook := func(block *types.Block) (*types.Block, error) { + appendM2HeaderHook := func(block *types.Block) (*types.Block, bool, error) { eb, err := eth.Etherbase() if err != nil { log.Error("Cannot get etherbase for append m2 header", "err", err) - return block, fmt.Errorf("etherbase missing: %v", err) + return block, false, fmt.Errorf("etherbase missing: %v", err) } m1, err := c.RecoverSigner(block.Header()) if err != nil { - return block, fmt.Errorf("can't get block creator: %v", err) + return block, false, fmt.Errorf("can't get block creator: %v", err) } m2, err := c.GetValidator(m1, eth.blockchain, block.Header()) if err != nil { - return block, fmt.Errorf("can't get block validator: %v", err) + return block, false, fmt.Errorf("can't get block validator: %v", err) } if m2 == eb { wallet, _ := eth.accountManager.Find(accounts.Account{Address: eb}) header := block.Header() sighash, _ := wallet.SignHash(accounts.Account{Address: eb}, posv.SigHash(header).Bytes()) header.Validator = sighash - block = types.NewBlockWithHeader(header).WithBody(block.Transactions(), block.Uncles()) + return types.NewBlockWithHeader(header).WithBody(block.Transactions(), block.Uncles()), true, nil } - - return block, nil + return block, false, nil } eth.protocolManager.fetcher.SetSignHook(signHook) eth.protocolManager.fetcher.SetAppendM2HeaderHook(appendM2HeaderHook) - // Hook prepares validators M2 for the current epoch - c.HookValidator = func(header *types.Header, signers []common.Address) error { + // Hook prepares validators M2 for the current epoch at checkpoint block + c.HookValidator = func(header *types.Header, signers []common.Address) ([]byte, error) { start := time.Now() - number := header.Number.Int64() - if number > 0 && number%common.EpocBlockRandomize == 0 { - validators, err := GetValidators(eth.blockchain, signers) - if err != nil { - return err - } - header.Validators = validators + validators, err := GetValidators(eth.blockchain, signers) + if err != nil { + return []byte{}, err } + header.Validators = validators log.Debug("Time Calculated HookValidator ", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start))) - return nil + return validators, nil } // Hook scans for bad masternodes and decide to penalty them @@ -301,8 +297,8 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { if foudationWalletAddr == (common.Address{}) { log.Error("Foundation Wallet Address is empty", "error", foudationWalletAddr) } - start := time.Now() if number > 0 && number-rCheckpoint > 0 && foudationWalletAddr != (common.Address{}) { + start := time.Now() // Get signers in blockSigner smartcontract. addr := common.HexToAddress(common.BlockSigners) // Get reward inflation. @@ -334,8 +330,8 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { } } } + log.Debug("Time Calculated HookReward ", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start))) } - log.Debug("Time Calculated HookReward ", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start))) return nil } @@ -359,7 +355,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { currentHeader := eth.blockchain.CurrentHeader() snap, err := c.GetSnapshot(eth.blockchain, currentHeader) if err != nil { - log.Error("Can't get snap shot with current header ", "number", currentHeader.Number, "hash", currentHeader.Hash().Hex()) + log.Error("Can't get snapshot with current header ", "number", currentHeader.Number, "hash", currentHeader.Hash().Hex()) return false } if _, ok := snap.Signers[address]; ok { diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 17fd41cdd6..4c285db2e6 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -47,10 +47,10 @@ var ( MaxForkAncestry = 3 * params.EpochDuration // Maximum chain reorganisation rttMinEstimate = 2 * time.Second // Minimum round-trip time to target for download requests - rttMaxEstimate = 20 * time.Second // Maximum rount-trip time to target for download requests + rttMaxEstimate = 5 * time.Second // Maximum rount-trip time to target for download requests rttMinConfidence = 0.1 // Worse confidence factor in our estimated RTT value - ttlScaling = 3 // Constant scaling factor for RTT -> TTL conversion - ttlLimit = time.Minute // Maximum TTL allowance to prevent reaching crazy timeouts + ttlScaling = 2 // Constant scaling factor for RTT -> TTL conversion + ttlLimit = 5 * time.Second // Maximum TTL allowance to prevent reaching crazy timeouts qosTuningPeers = 5 // Number of peers to tune based on (best peers) qosConfidenceCap = 10 // Number of peers above which not to modify RTT confidence diff --git a/eth/downloader/queue.go b/eth/downloader/queue.go index 359cce54b5..8e6c91166e 100644 --- a/eth/downloader/queue.go +++ b/eth/downloader/queue.go @@ -146,9 +146,7 @@ func (q *queue) Reset() { // Close marks the end of the sync, unblocking WaitResults. // It may be called even if the queue is already closed. func (q *queue) Close() { - q.lock.Lock() q.closed = true - q.lock.Unlock() q.active.Broadcast() } diff --git a/eth/fetcher/fetcher.go b/eth/fetcher/fetcher.go index dbb7de94d4..0b94b50d7a 100644 --- a/eth/fetcher/fetcher.go +++ b/eth/fetcher/fetcher.go @@ -62,8 +62,10 @@ type blockBroadcasterFn func(block *types.Block, propagate bool) // chainHeightFn is a callback type to retrieve the current chain height. type chainHeightFn func() uint64 -// chainInsertFn is a callback type to insert a batch of blocks into the local chain. -type chainInsertFn func(blocks types.Blocks) (int, error) +// blockInsertFn is a callback type to insert a batch of blocks into the local chain. +type blockInsertFn func(block *types.Block) error + +type blockPrepareFn func(block *types.Block) error // peerDropFn is a callback type for dropping a peer detected as malicious. type peerDropFn func(id string) @@ -135,8 +137,9 @@ type Fetcher struct { verifyHeader headerVerifierFn // Checks if a block's headers have a valid proof of work broadcastBlock blockBroadcasterFn // Broadcasts a block to connected peers chainHeight chainHeightFn // Retrieves the current chain's height - insertChain chainInsertFn // Injects a batch of blocks into the chain - dropPeer peerDropFn // Drops a peer for misbehaving + insertBlock blockInsertFn // Injects a batch of blocks into the chain + prepareBlock blockPrepareFn + dropPeer peerDropFn // Drops a peer for misbehaving // Testing hooks announceChangeHook func(common.Hash, bool) // Method to call upon adding or deleting a hash from the announce list @@ -144,11 +147,11 @@ type Fetcher struct { fetchingHook func([]common.Hash) // Method to call upon starting a block (eth/61) or header (eth/62) fetch completingHook func([]common.Hash) // Method to call upon starting a block body fetch (eth/62) signHook func(*types.Block) error - appendM2HeaderHook func(*types.Block) (*types.Block, error) + appendM2HeaderHook func(*types.Block) (*types.Block, bool, error) } // New creates a block fetcher to retrieve blocks based on hash announcements. -func New(getBlock blockRetrievalFn, verifyHeader headerVerifierFn, broadcastBlock blockBroadcasterFn, chainHeight chainHeightFn, insertChain chainInsertFn, dropPeer peerDropFn) *Fetcher { +func New(getBlock blockRetrievalFn, verifyHeader headerVerifierFn, broadcastBlock blockBroadcasterFn, chainHeight chainHeightFn, insertBlock blockInsertFn, prepareBlock blockPrepareFn, dropPeer peerDropFn) *Fetcher { knownBlocks, _ := lru.NewARC(blockLimit) return &Fetcher{ notify: make(chan *announce), @@ -171,7 +174,8 @@ func New(getBlock blockRetrievalFn, verifyHeader headerVerifierFn, broadcastBloc verifyHeader: verifyHeader, broadcastBlock: broadcastBlock, chainHeight: chainHeight, - insertChain: insertChain, + insertBlock: insertBlock, + prepareBlock: prepareBlock, dropPeer: dropPeer, } } @@ -605,7 +609,7 @@ func (f *Fetcher) rescheduleComplete(complete *time.Timer) { func (f *Fetcher) enqueue(peer string, block *types.Block) { hash := block.Hash() if f.knowns.Contains(hash) { - log.Debug("Discarded propagated block, known block", "peer", peer, "number", block.Number(), "hash", hash, "limit", blockLimit) + log.Trace("Discarded propagated block, known block", "peer", peer, "number", block.Number(), "hash", hash, "limit", blockLimit) return } // Ensure the peer isn't DOSing us @@ -657,40 +661,56 @@ func (f *Fetcher) insert(peer string, block *types.Block) { log.Debug("Unknown parent of propagated block", "peer", peer, "number", block.Number(), "hash", hash, "parent", block.ParentHash()) return } + fastBroadCast := true again: + err := f.verifyHeader(block.Header()) // Quickly validate the header and propagate the block if it passes - switch err := f.verifyHeader(block.Header()); err { + switch err { case nil: // All ok, quickly propagate to our peers propBroadcastOutTimer.UpdateSince(block.ReceivedAt) - go f.broadcastBlock(block, true) + if fastBroadCast { + go f.broadcastBlock(block, true) + } case consensus.ErrFutureBlock: delay := time.Unix(block.Time().Int64(), 0).Sub(time.Now()) // nolint: gosimple - time.Sleep(delay) log.Info("Receive future block", "number", block.NumberU64(), "hash", block.Hash().Hex(), "delay", delay) + time.Sleep(delay) goto again case consensus.ErrNoValidatorSignature: newBlock := block + var errM2 error + isM2 := false if f.appendM2HeaderHook != nil { - if newBlock, err = f.appendM2HeaderHook(block); err != nil { - log.Error("Append m2 to block header fail", "err", err) + if newBlock, isM2, errM2 = f.appendM2HeaderHook(block); errM2 != nil { + log.Error("Append m2 to block header fail", "err", errM2) return } } - if newBlock.Hash() == block.Hash() { + if !isM2 { go f.broadcastBlock(block, true) + if err := f.prepareBlock(block); err != nil { + log.Debug("Propagated block prepare failed", "peer", peer, "number", block.Number(), "hash", hash, "err", err) + return + } + return + } + log.Debug("Append M2 to header block", "numer", block.NumberU64(), "hahs", block.Hash()) + if err := f.prepareBlock(block); err != nil { + log.Debug("Propagated block prepare failed", "peer", peer, "number", block.Number(), "hash", hash, "err", err) return } block = newBlock + fastBroadCast = false + goto again default: // Something went very wrong, drop the peer log.Debug("Propagated block verification failed", "peer", peer, "number", block.Number(), "hash", hash, "err", err) f.dropPeer(peer) return } - // Run the actual import and log any issues - if _, err := f.insertChain(types.Blocks{block}); err != nil { + if err := f.insertBlock(block); err != nil { log.Debug("Propagated block import failed", "peer", peer, "number", block.Number(), "hash", hash, "err", err) return } @@ -703,8 +723,9 @@ func (f *Fetcher) insert(peer string, block *types.Block) { } // If import succeeded, broadcast the block propAnnounceOutTimer.UpdateSince(block.ReceivedAt) - go f.broadcastBlock(block, true) - go f.broadcastBlock(block, false) + if !fastBroadCast { + go f.broadcastBlock(block, true) + } }() } @@ -768,6 +789,6 @@ func (f *Fetcher) SetSignHook(signHook func(*types.Block) error) { } // Bind append m2 to block header hook when imported into chain. -func (f *Fetcher) SetAppendM2HeaderHook(appendM2HeaderHook func(*types.Block) (*types.Block, error)) { +func (f *Fetcher) SetAppendM2HeaderHook(appendM2HeaderHook func(*types.Block) (*types.Block, bool, error)) { f.appendM2HeaderHook = appendM2HeaderHook } diff --git a/eth/fetcher/fetcher_test.go b/eth/fetcher/fetcher_test.go index af9a5a6b44..b4f4cebf1a 100644 --- a/eth/fetcher/fetcher_test.go +++ b/eth/fetcher/fetcher_test.go @@ -92,7 +92,7 @@ func newTester() *fetcherTester { blocks: map[common.Hash]*types.Block{genesis.Hash(): genesis}, drops: make(map[string]bool), } - tester.fetcher = New(tester.getBlock, tester.verifyHeader, tester.broadcastBlock, tester.chainHeight, tester.insertChain, tester.dropPeer) + tester.fetcher = New(tester.getBlock, tester.verifyHeader, tester.broadcastBlock, tester.chainHeight, tester.insertBlock, tester.prepareBlock, tester.dropPeer) tester.fetcher.Start() return tester @@ -123,7 +123,7 @@ func (f *fetcherTester) chainHeight() uint64 { return f.blocks[f.hashes[len(f.hashes)-1]].NumberU64() } -// insertChain injects a new blocks into the simulated chain. +// insertBlock injects a new blocks into the simulated chain. func (f *fetcherTester) insertChain(blocks types.Blocks) (int, error) { f.lock.Lock() defer f.lock.Unlock() @@ -144,6 +144,31 @@ func (f *fetcherTester) insertChain(blocks types.Blocks) (int, error) { return 0, nil } +// insertBlock injects a new blocks into the simulated chain. +func (f *fetcherTester) insertBlock(block *types.Block) error { + f.lock.Lock() + defer f.lock.Unlock() + + // Make sure the parent in known + if _, ok := f.blocks[block.ParentHash()]; !ok { + return errors.New("unknown parent") + } + // Discard any new blocks if the same height already exists + if block.NumberU64() <= f.blocks[f.hashes[len(f.hashes)-1]].NumberU64() { + return nil + } + // Otherwise build our current chain + f.hashes = append(f.hashes, block.Hash()) + f.blocks[block.Hash()] = block + + return nil +} + +// insertBlock injects a new blocks into the simulated chain. +func (f *fetcherTester) prepareBlock(block *types.Block) error { + return nil +} + // dropPeer is an emulator for the peer removal, simply accumulating the various // peers dropped by the fetcher. func (f *fetcherTester) dropPeer(peer string) { @@ -512,9 +537,9 @@ func testImportDeduplication(t *testing.T, protocol int) { bodyFetcher := tester.makeBodyFetcher("valid", blocks, 0) counter := uint32(0) - tester.fetcher.insertChain = func(blocks types.Blocks) (int, error) { - atomic.AddUint32(&counter, uint32(len(blocks))) - return tester.insertChain(blocks) + tester.fetcher.insertBlock = func(block *types.Block) error { + atomic.AddUint32(&counter, uint32(1)) + return tester.insertBlock(block) } // Instrument the fetching and imported events fetching := make(chan []common.Hash) diff --git a/eth/handler.go b/eth/handler.go index 181ffa704e..f1a408d53d 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -20,6 +20,7 @@ import ( "encoding/json" "errors" "fmt" + "github.com/hashicorp/golang-lru" "math/big" "sync" "sync/atomic" @@ -82,8 +83,6 @@ type ProtocolManager struct { eventMux *event.TypeMux txCh chan core.TxPreEvent txSub event.Subscription - specialTxCh chan core.TxPreEvent - specialTxSub event.Subscription minedBlockSub *event.TypeMuxSubscription // channels for fetcher, syncer, txsyncLoop @@ -94,12 +93,14 @@ type ProtocolManager struct { // wait group is used for graceful shutdowns during downloading // and processing - wg sync.WaitGroup + wg sync.WaitGroup + knownTxs *lru.Cache } // NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable // with the ethereum network. func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, networkId uint64, mux *event.TypeMux, txpool txPool, engine consensus.Engine, blockchain *core.BlockChain, chaindb ethdb.Database) (*ProtocolManager, error) { + knownTxs, _ := lru.New(maxKnownTxs) // Create the protocol manager with the base fields manager := &ProtocolManager{ networkId: networkId, @@ -112,6 +113,7 @@ func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, ne noMorePeers: make(chan struct{}), txsyncCh: make(chan *txsync), quitSync: make(chan struct{}), + knownTxs: knownTxs, } // Figure out whether to allow fast sync or not if mode == downloader.FastSync && blockchain.CurrentBlock().NumberU64() > 0 { @@ -168,16 +170,26 @@ func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, ne heighter := func() uint64 { return blockchain.CurrentBlock().NumberU64() } - inserter := func(blocks types.Blocks) (int, error) { + inserter := func(block *types.Block) error { // If fast sync is running, deny importing weird blocks if atomic.LoadUint32(&manager.fastSync) == 1 { - log.Warn("Discarded bad propagated block", "number", blocks[0].Number(), "hash", blocks[0].Hash()) - return 0, nil + log.Warn("Discarded bad propagated block", "number", block.Number(), "hash", block.Hash()) + return nil } atomic.StoreUint32(&manager.acceptTxs, 1) // Mark initial sync done on any fetcher import - return manager.blockchain.InsertChain(blocks) + return manager.blockchain.InsertBlock(block) } - manager.fetcher = fetcher.New(blockchain.GetBlockByHash, validator, manager.BroadcastBlock, heighter, inserter, manager.removePeer) + + prepare := func(block *types.Block) error { + // If fast sync is running, deny importing weird blocks + if atomic.LoadUint32(&manager.fastSync) == 1 { + log.Warn("Discarded bad propagated block", "number", block.Number(), "hash", block.Hash()) + return nil + } + atomic.StoreUint32(&manager.acceptTxs, 1) // Mark initial sync done on any fetcher import + return manager.blockchain.PrepareBlock(block) + } + manager.fetcher = fetcher.New(blockchain.GetBlockByHash, validator, manager.BroadcastBlock, heighter, inserter, prepare, manager.removePeer) return manager, nil } @@ -209,11 +221,6 @@ func (pm *ProtocolManager) Start(maxPeers int) { pm.txSub = pm.txpool.SubscribeTxPreEvent(pm.txCh) go pm.txBroadcastLoop() - // broadcast special transactions - pm.specialTxCh = make(chan core.TxPreEvent, txChanSize) - pm.specialTxSub = pm.txpool.SubscribeSpecialTxPreEvent(pm.specialTxCh) - go pm.specialTxBroadcastLoop() - // broadcast mined blocks pm.minedBlockSub = pm.eventMux.Subscribe(core.NewMinedBlockEvent{}) go pm.minedBroadcastLoop() @@ -227,7 +234,6 @@ func (pm *ProtocolManager) Stop() { log.Info("Stopping Ethereum protocol") pm.txSub.Unsubscribe() // quits txBroadcastLoop - pm.specialTxSub.Unsubscribe() // quits specialTxBroadcastLoop pm.minedBlockSub.Unsubscribe() // quits blockBroadcastLoop // Quit the sync loop. @@ -651,17 +657,14 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { trueTD = new(big.Int).Sub(request.TD, request.Block.Difficulty()) ) // Update the peers total difficulty if better than the previous - _, td := p.Head() - currentBlock := pm.blockchain.CurrentBlock() - currentTd := pm.blockchain.GetTd(currentBlock.Hash(), currentBlock.NumberU64()) - log.Debug("NewBlockMsg", "p", p, "number", request.Block.NumberU64(), "trueTD", trueTD, "td", td, "currentTd", currentTd) - if trueTD.Cmp(td) > 0 { + if _, td := p.Head(); trueTD.Cmp(td) > 0 { p.SetHead(trueHead, trueTD) // Schedule a sync if above ours. Note, this will not fire a sync for a gap of // a singe block (as the true TD is below the propagated block), however this // scenario should easily be covered by the fetcher. - if trueTD.Cmp(currentTd) > 0 { + currentBlock := pm.blockchain.CurrentBlock() + if trueTD.Cmp(pm.blockchain.GetTd(currentBlock.Hash(), currentBlock.NumberU64())) > 0 { go pm.synchronise(p) } } @@ -676,12 +679,19 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { if err := msg.Decode(&txs); err != nil { return errResp(ErrDecode, "msg %v: %v", msg, err) } + var unkownTxs []*types.Transaction for i, tx := range txs { // Validate and mark the remote transaction if tx == nil { return errResp(ErrDecode, "transaction %d is nil", i) } p.MarkTransaction(tx.Hash()) + exist, _ := pm.knownTxs.ContainsOrAdd(tx.Hash(), true) + if !exist { + unkownTxs = append(unkownTxs, tx) + } else { + log.Trace("Discard known tx", "hash", tx.Hash(), "nonce", tx.Nonce(), "to", tx.To()) + } } pm.txpool.AddRemotes(txs) @@ -735,24 +745,14 @@ func (pm *ProtocolManager) BroadcastTx(hash common.Hash, tx *types.Transaction) log.Trace("Broadcast transaction", "hash", hash, "recipients", len(peers)) } -func (pm *ProtocolManager) BroadcastSpecialTx(hash common.Hash, tx *types.Transaction) { - // Broadcast transaction to a batch of peers not knowing about it - peers := pm.peers.PeersWithoutTx(hash) - //FIXME include this again: peers = peers[:int(math.Sqrt(float64(len(peers))))] - for _, peer := range peers { - peer.SendSpecialTransactions(tx) - } - log.Trace("Broadcast special transaction", "hash", hash, "recipients", len(peers)) -} - // Mined broadcast loop func (self *ProtocolManager) minedBroadcastLoop() { // automatically stops if unsubscribe for obj := range self.minedBlockSub.Chan() { switch ev := obj.Data.(type) { case core.NewMinedBlockEvent: - self.BroadcastBlock(ev.Block, true) // First propagate block to peers - self.BroadcastBlock(ev.Block, false) // Only then announce to the rest + self.BroadcastBlock(ev.Block, true) // First propagate block to peers + //self.BroadcastBlock(ev.Block, false) // Only then announce to the rest } } } @@ -770,19 +770,6 @@ func (self *ProtocolManager) txBroadcastLoop() { } } -func (self *ProtocolManager) specialTxBroadcastLoop() { - for { - select { - case event := <-self.specialTxCh: - self.BroadcastSpecialTx(event.Tx.Hash(), event.Tx) - - // Err() channel will be closed when unsubscribing. - case <-self.specialTxSub.Err(): - return - } - } -} - // NodeInfo represents a short summary of the Ethereum sub-protocol metadata // known about the host peer. type NodeInfo struct { diff --git a/eth/helper_test.go b/eth/helper_test.go index ca686df808..2b05cea801 100644 --- a/eth/helper_test.go +++ b/eth/helper_test.go @@ -128,10 +128,6 @@ func (p *testTxPool) SubscribeTxPreEvent(ch chan<- core.TxPreEvent) event.Subscr return p.txFeed.Subscribe(ch) } -func (p *testTxPool) SubscribeSpecialTxPreEvent(ch chan<- core.TxPreEvent) event.Subscription { - return p.txFeed.Subscribe(ch) -} - // newTestTransaction create a new dummy transaction. func newTestTransaction(from *ecdsa.PrivateKey, nonce uint64, datasize int) *types.Transaction { tx := types.NewTransaction(nonce, common.Address{}, big.NewInt(0), 100000, big.NewInt(0), make([]byte, datasize)) diff --git a/eth/peer.go b/eth/peer.go index 75813fe93a..47a1075486 100644 --- a/eth/peer.go +++ b/eth/peer.go @@ -25,7 +25,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/rlp" "gopkg.in/fatih/set.v0" @@ -141,15 +140,6 @@ func (p *peer) SendTransactions(txs types.Transactions) error { return p2p.Send(p.rw, TxMsg, txs) } -func (p *peer) SendSpecialTransactions(tx *types.Transaction) error { - p.knownTxs.Add(tx.Hash()) - if p.pairRw != nil { - return p2p.Send(p.pairRw, TxMsg, types.Transactions{tx}) - } else { - return p2p.Send(p.rw, TxMsg, types.Transactions{tx}) - } -} - // SendNewBlockHashes announces the availability of a number of blocks through // a hash notification. func (p *peer) SendNewBlockHashes(hashes []common.Hash, numbers []uint64) error { @@ -168,81 +158,123 @@ func (p *peer) SendNewBlockHashes(hashes []common.Hash, numbers []uint64) error func (p *peer) SendNewBlock(block *types.Block, td *big.Int) error { p.knownBlocks.Add(block.Hash()) if p.pairRw != nil { - log.Trace("p2p send new block to the pairRw connection", "p", p, "number", block.NumberU64()) return p2p.Send(p.pairRw, NewBlockMsg, []interface{}{block, td}) } else { return p2p.Send(p.rw, NewBlockMsg, []interface{}{block, td}) } - } // SendBlockHeaders sends a batch of block headers to the remote peer. func (p *peer) SendBlockHeaders(headers []*types.Header) error { - return p2p.Send(p.rw, BlockHeadersMsg, headers) + if p.pairRw != nil { + return p2p.Send(p.pairRw, BlockHeadersMsg, headers) + } else { + return p2p.Send(p.rw, BlockHeadersMsg, headers) + } } // SendBlockBodies sends a batch of block contents to the remote peer. func (p *peer) SendBlockBodies(bodies []*blockBody) error { - return p2p.Send(p.rw, BlockBodiesMsg, blockBodiesData(bodies)) + if p.pairRw != nil { + return p2p.Send(p.pairRw, BlockBodiesMsg, blockBodiesData(bodies)) + } else { + return p2p.Send(p.rw, BlockBodiesMsg, blockBodiesData(bodies)) + } } // SendBlockBodiesRLP sends a batch of block contents to the remote peer from // an already RLP encoded format. func (p *peer) SendBlockBodiesRLP(bodies []rlp.RawValue) error { - return p2p.Send(p.rw, BlockBodiesMsg, bodies) + if p.pairRw != nil { + return p2p.Send(p.pairRw, BlockBodiesMsg, bodies) + } else { + return p2p.Send(p.rw, BlockBodiesMsg, bodies) + } } // SendNodeDataRLP sends a batch of arbitrary internal data, corresponding to the // hashes requested. func (p *peer) SendNodeData(data [][]byte) error { - return p2p.Send(p.rw, NodeDataMsg, data) + if p.pairRw != nil { + return p2p.Send(p.pairRw, NodeDataMsg, data) + } else { + return p2p.Send(p.rw, NodeDataMsg, data) + } } // SendReceiptsRLP sends a batch of transaction receipts, corresponding to the // ones requested from an already RLP encoded format. func (p *peer) SendReceiptsRLP(receipts []rlp.RawValue) error { - return p2p.Send(p.rw, ReceiptsMsg, receipts) + if p.pairRw != nil { + return p2p.Send(p.pairRw, ReceiptsMsg, receipts) + } else { + return p2p.Send(p.rw, ReceiptsMsg, receipts) + } } // RequestOneHeader is a wrapper around the header query functions to fetch a // single header. It is used solely by the fetcher. func (p *peer) RequestOneHeader(hash common.Hash) error { p.Log().Debug("Fetching single header", "hash", hash) - return p2p.Send(p.rw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Hash: hash}, Amount: uint64(1), Skip: uint64(0), Reverse: false}) + if p.pairRw != nil { + return p2p.Send(p.pairRw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Hash: hash}, Amount: uint64(1), Skip: uint64(0), Reverse: false}) + } else { + return p2p.Send(p.rw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Hash: hash}, Amount: uint64(1), Skip: uint64(0), Reverse: false}) + } } // RequestHeadersByHash fetches a batch of blocks' headers corresponding to the // specified header query, based on the hash of an origin block. func (p *peer) RequestHeadersByHash(origin common.Hash, amount int, skip int, reverse bool) error { p.Log().Debug("Fetching batch of headers", "count", amount, "fromhash", origin, "skip", skip, "reverse", reverse) - return p2p.Send(p.rw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Hash: origin}, Amount: uint64(amount), Skip: uint64(skip), Reverse: reverse}) + if p.pairRw != nil { + return p2p.Send(p.pairRw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Hash: origin}, Amount: uint64(amount), Skip: uint64(skip), Reverse: reverse}) + } else { + return p2p.Send(p.rw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Hash: origin}, Amount: uint64(amount), Skip: uint64(skip), Reverse: reverse}) + } } // RequestHeadersByNumber fetches a batch of blocks' headers corresponding to the // specified header query, based on the number of an origin block. func (p *peer) RequestHeadersByNumber(origin uint64, amount int, skip int, reverse bool) error { p.Log().Debug("Fetching batch of headers", "count", amount, "fromnum", origin, "skip", skip, "reverse", reverse) - return p2p.Send(p.rw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Number: origin}, Amount: uint64(amount), Skip: uint64(skip), Reverse: reverse}) + if p.pairRw != nil { + return p2p.Send(p.pairRw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Number: origin}, Amount: uint64(amount), Skip: uint64(skip), Reverse: reverse}) + } else { + return p2p.Send(p.rw, GetBlockHeadersMsg, &getBlockHeadersData{Origin: hashOrNumber{Number: origin}, Amount: uint64(amount), Skip: uint64(skip), Reverse: reverse}) + } } // RequestBodies fetches a batch of blocks' bodies corresponding to the hashes // specified. func (p *peer) RequestBodies(hashes []common.Hash) error { p.Log().Debug("Fetching batch of block bodies", "count", len(hashes)) - return p2p.Send(p.rw, GetBlockBodiesMsg, hashes) + if p.pairRw != nil { + return p2p.Send(p.pairRw, GetBlockBodiesMsg, hashes) + } else { + return p2p.Send(p.rw, GetBlockBodiesMsg, hashes) + } } // RequestNodeData fetches a batch of arbitrary data from a node's known state // data, corresponding to the specified hashes. func (p *peer) RequestNodeData(hashes []common.Hash) error { p.Log().Debug("Fetching batch of state data", "count", len(hashes)) - return p2p.Send(p.rw, GetNodeDataMsg, hashes) + if p.pairRw != nil { + return p2p.Send(p.pairRw, GetNodeDataMsg, hashes) + } else { + return p2p.Send(p.rw, GetNodeDataMsg, hashes) + } } // RequestReceipts fetches a batch of transaction receipts from a remote node. func (p *peer) RequestReceipts(hashes []common.Hash) error { p.Log().Debug("Fetching batch of receipts", "count", len(hashes)) - return p2p.Send(p.rw, GetReceiptsMsg, hashes) + if p.pairRw != nil { + return p2p.Send(p.pairRw, GetReceiptsMsg, hashes) + } else { + return p2p.Send(p.rw, GetReceiptsMsg, hashes) + } } // Handshake executes the eth protocol handshake, negotiating version number, diff --git a/eth/protocol.go b/eth/protocol.go index f44a01f020..cd7db57f23 100644 --- a/eth/protocol.go +++ b/eth/protocol.go @@ -106,7 +106,6 @@ type txPool interface { // SubscribeTxPreEvent should return an event subscription of // TxPreEvent and send events to the given channel. SubscribeTxPreEvent(chan<- core.TxPreEvent) event.Subscription - SubscribeSpecialTxPreEvent(chan<- core.TxPreEvent) event.Subscription } // statusData is the network packet for the status message. diff --git a/eth/sync.go b/eth/sync.go index 89f1f15c51..770d6db277 100644 --- a/eth/sync.go +++ b/eth/sync.go @@ -170,7 +170,6 @@ func (pm *ProtocolManager) synchronise(peer *peer) { currentBlock := pm.blockchain.CurrentBlock() td := pm.blockchain.GetTd(currentBlock.Hash(), currentBlock.NumberU64()) pHead, pTd := peer.Head() - log.Debug("ProtocolManager synchronise ", "p", peer, "pTd", pTd, "currentTd", td) if pTd.Cmp(td) <= 0 { return } @@ -205,13 +204,13 @@ func (pm *ProtocolManager) synchronise(peer *peer) { atomic.StoreUint32(&pm.fastSync, 0) } atomic.StoreUint32(&pm.acceptTxs, 1) // Mark initial sync done - if head := pm.blockchain.CurrentBlock(); head.NumberU64() > 0 { - // We've completed a sync cycle, notify all peers of new state. This path is - // essential in star-topology networks where a gateway node needs to notify - // all its out-of-date peers of the availability of a new block. This failure - // scenario will most often crop up in private and hackathon networks with - // degenerate connectivity, but it should be healthy for the mainnet too to - // more reliably update peers or the local TD state. - go pm.BroadcastBlock(head, false) - } + //if head := pm.blockchain.CurrentBlock(); head.NumberU64() > 0 { + // // We've completed a sync cycle, notify all peers of new state. This path is + // // essential in star-topology networks where a gateway node needs to notify + // // all its out-of-date peers of the availability of a new block. This failure + // // scenario will most often crop up in private and hackathon networks with + // // degenerate connectivity, but it should be healthy for the mainnet too to + // // more reliably update peers or the local TD state. + // go pm.BroadcastBlock(head, false) + //} } diff --git a/miner/miner.go b/miner/miner.go index d9256e9787..4bfab42f65 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -57,12 +57,12 @@ type Miner struct { shouldStart int32 // should start indicates whether we should start after sync } -func New(eth Backend, config *params.ChainConfig, mux *event.TypeMux, engine consensus.Engine) *Miner { +func New(eth Backend, config *params.ChainConfig, mux *event.TypeMux, engine consensus.Engine, announceTxs bool) *Miner { miner := &Miner{ eth: eth, mux: mux, engine: engine, - worker: newWorker(config, engine, common.Address{}, eth, mux), + worker: newWorker(config, engine, common.Address{}, eth, mux, announceTxs), canStart: 1, } miner.Register(NewCpuAgent(eth.BlockChain(), engine)) @@ -77,7 +77,6 @@ func New(eth Backend, config *params.ChainConfig, mux *event.TypeMux, engine con // and halt your mining operation for as long as the DOS continues. func (self *Miner) update() { events := self.mux.Subscribe(downloader.StartEvent{}, downloader.DoneEvent{}, downloader.FailedEvent{}) -out: for ev := range events.Chan() { switch ev.Data.(type) { case downloader.StartEvent: @@ -95,10 +94,6 @@ out: if shouldStart { self.Start(self.coinbase) } - // unsubscribe. we're only interested in this event once - events.Unsubscribe() - // stop immediately and ignore all further pending events - break out } } } diff --git a/miner/worker.go b/miner/worker.go index a774cd1a06..ffba0b1ca1 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -55,7 +55,7 @@ const ( // timeout waiting for M1 waitPeriod = 10 // timeout for checkpoint. - waitPeriodCheckpoint = 60 + waitPeriodCheckpoint = 30 ) // Agent can register themself with the worker @@ -130,11 +130,13 @@ type worker struct { unconfirmed *unconfirmedBlocks // set of locally mined blocks pending canonicalness confirmations // atomic status counters - mining int32 - atWork int32 + mining int32 + atWork int32 + announceTxs bool + lastParentBlockCommit string } -func newWorker(config *params.ChainConfig, engine consensus.Engine, coinbase common.Address, eth Backend, mux *event.TypeMux) *worker { +func newWorker(config *params.ChainConfig, engine consensus.Engine, coinbase common.Address, eth Backend, mux *event.TypeMux, announceTxs bool) *worker { worker := &worker{ config: config, engine: engine, @@ -151,9 +153,12 @@ func newWorker(config *params.ChainConfig, engine consensus.Engine, coinbase com coinbase: coinbase, agents: make(map[Agent]struct{}), unconfirmed: newUnconfirmedBlocks(eth.BlockChain(), miningLogAtDepth), + announceTxs: announceTxs, + } + if worker.announceTxs { + // Subscribe TxPreEvent for tx pool + worker.txSub = eth.TxPool().SubscribeTxPreEvent(worker.txCh) } - // Subscribe TxPreEvent for tx pool - worker.txSub = eth.TxPool().SubscribeTxPreEvent(worker.txCh) // Subscribe events for blockchain worker.chainHeadSub = eth.BlockChain().SubscribeChainHeadEvent(worker.chainHeadCh) worker.chainSideSub = eth.BlockChain().SubscribeChainSideEvent(worker.chainSideCh) @@ -248,23 +253,47 @@ func (self *worker) unregister(agent Agent) { } func (self *worker) update() { - defer self.txSub.Unsubscribe() + if self.announceTxs { + defer self.txSub.Unsubscribe() + } defer self.chainHeadSub.Unsubscribe() defer self.chainSideSub.Unsubscribe() - + timeout := time.NewTimer(waitPeriod * time.Second) + c := make(chan struct{}) + finish := make(chan struct{}) + defer close(finish) + defer timeout.Stop() + go func() { + for { + // A real event arrived, process interesting content + select { + case <-timeout.C: + c <- struct{}{} + case <-finish: + return + } + } + }() for { // A real event arrived, process interesting content select { - // Handle ChainHeadEvent + case <-c: + if atomic.LoadInt32(&self.mining) == 1 { + self.commitNewWork() + } + timeout.Reset(waitPeriod * time.Second) + // Handle ChainHeadEvent case <-self.chainHeadCh: self.commitNewWork() + timeout.Reset(waitPeriod * time.Second) // Handle ChainSideEvent case ev := <-self.chainSideCh: - self.uncleMu.Lock() - self.possibleUncles[ev.Block.Hash()] = ev.Block - self.uncleMu.Unlock() - + if self.config.Posv == nil { + self.uncleMu.Lock() + self.possibleUncles[ev.Block.Hash()] = ev.Block + self.uncleMu.Unlock() + } // Handle TxPreEvent case ev := <-self.txCh: // Apply transaction to the pending state if we're not mining @@ -282,9 +311,6 @@ func (self *worker) update() { self.commitNewWork() } } - // System stopped - case <-self.txSub.Err(): - return case <-self.chainHeadSub.Err(): return case <-self.chainSideSub.Err(): @@ -422,13 +448,15 @@ func (self *worker) makeCurrent(parent *types.Block, header *types.Header) error createdAt: time.Now(), } - // when 08 is processed ancestors contain 07 (quick block) - for _, ancestor := range self.chain.GetBlocksFromHash(parent.Hash(), 7) { - for _, uncle := range ancestor.Uncles() { - work.family.Add(uncle.Hash()) + if self.config.Posv == nil { + // when 08 is processed ancestors contain 07 (quick block) + for _, ancestor := range self.chain.GetBlocksFromHash(parent.Hash(), 7) { + for _, uncle := range ancestor.Uncles() { + work.family.Add(uncle.Hash()) + } + work.family.Add(ancestor.Hash()) + work.ancestors.Add(ancestor.Hash()) } - work.family.Add(ancestor.Hash()) - work.ancestors.Add(ancestor.Hash()) } // Keep track of transactions which return errors so they can be removed @@ -444,17 +472,6 @@ func abs(x int64) int64 { return x } -func hop(len, pre, cur int) int { - switch { - case pre < cur: - return cur - (pre + 1) - case pre > cur: - return (len - pre) + (cur - 1) - default: - return len - 1 - } -} - func (self *worker) commitNewWork() { self.mu.Lock() defer self.mu.Unlock() @@ -466,6 +483,13 @@ func (self *worker) commitNewWork() { tstart := time.Now() parent := self.chain.CurrentBlock() var signers map[common.Address]struct{} + if parent.Hash().Hex() == self.lastParentBlockCommit { + return + } + if !self.announceTxs && atomic.LoadInt32(&self.mining) == 0 { + return + } + // Only try to commit new work if we are mining if atomic.LoadInt32(&self.mining) == 1 { // check if we are right after parent's coinbase in the list @@ -473,14 +497,7 @@ func (self *worker) commitNewWork() { if self.config.Posv != nil { // get masternodes set from latest checkpoint c := self.engine.(*posv.Posv) - masternodes := c.GetMasternodes(self.chain, parent.Header()) - snap, err := c.GetSnapshot(self.chain, parent.Header()) - if err != nil { - log.Error("Failed when trying to commit new work", "err", err) - return - } - signers = snap.Signers - preIndex, curIndex, ok, err := posv.YourTurn(masternodes, snap, parent.Header(), self.coinbase) + len, preIndex, curIndex, ok, err := c.YourTurn(self.chain, parent.Header(),self.coinbase) if err != nil { log.Error("Failed when trying to commit new work", "err", err) return @@ -496,31 +513,22 @@ func (self *worker) commitNewWork() { // you're not allowed to create this block return } - h := hop(len(masternodes), preIndex, curIndex) + h := posv.Hop(len, preIndex, curIndex) gap := waitPeriod * int64(h) // Check nearest checkpoint block in hop range. nearest := self.config.Posv.Epoch - (parent.Header().Number.Uint64() % self.config.Posv.Epoch) if uint64(h) >= nearest { - gap += waitPeriodCheckpoint + gap = waitPeriodCheckpoint * int64(h) } log.Info("Distance from the parent block", "seconds", gap, "hops", h) - L: - select { - case newBlock := <-self.chainHeadCh: - self.chainHeadCh <- newBlock - if newBlock.Block.NumberU64() > parent.NumberU64() { - log.Info("New block has came already. Skip this turn", "new block", newBlock.Block.NumberU64(), "current block", parent.NumberU64()) - return - } - case <-time.After(time.Duration(gap) * time.Second): - // wait enough. It's my turn - log.Info("Wait enough. It's my turn", "waited seconds", gap) - break L + waitedTime := time.Now().Unix() - parent.Header().Time.Int64() + if gap > waitedTime { + return } + log.Info("Wait enough. It's my turn", "waited seconds", waitedTime) } } } - tstamp := tstart.Unix() if parent.Time().Cmp(new(big.Int).SetInt64(tstamp)) >= 0 { tstamp = parent.Time().Int64() + 1 @@ -545,7 +553,7 @@ func (self *worker) commitNewWork() { header.Coinbase = self.coinbase } if err := self.engine.Prepare(self.chain, header); err != nil { - log.Error("Failed to prepare header for mining", "err", err) + log.Error("Failed to prepare header for new block", "err", err) return } // If we are care about TheDAO hard-fork check whether to override the extra-data or not @@ -585,32 +593,34 @@ func (self *worker) commitNewWork() { uncles []*types.Header badUncles []common.Hash ) - for hash, uncle := range self.possibleUncles { - if len(uncles) == 2 { - break - } - if err := self.commitUncle(work, uncle.Header()); err != nil { - log.Trace("Bad uncle found and will be removed", "hash", hash) - log.Trace(fmt.Sprint(uncle)) + if self.config.Posv == nil { + for hash, uncle := range self.possibleUncles { + if len(uncles) == 2 { + break + } + if err := self.commitUncle(work, uncle.Header()); err != nil { + log.Trace("Bad uncle found and will be removed", "hash", hash) + log.Trace(fmt.Sprint(uncle)) - badUncles = append(badUncles, hash) - } else { - log.Debug("Committing new uncle to block", "hash", hash) - uncles = append(uncles, uncle.Header()) + badUncles = append(badUncles, hash) + } else { + log.Debug("Committing new uncle to block", "hash", hash) + uncles = append(uncles, uncle.Header()) + } + } + for _, hash := range badUncles { + delete(self.possibleUncles, hash) } - } - for _, hash := range badUncles { - delete(self.possibleUncles, hash) } // Create the new block to seal with the consensus engine if work.Block, err = self.engine.Finalize(self.chain, header, work.state, work.txs, uncles, work.receipts); err != nil { log.Error("Failed to finalize block for sealing", "err", err) return } - // We only care about logging if we're actually mining. if atomic.LoadInt32(&self.mining) == 1 { - log.Info("Commit new mining work", "number", work.Block.Number(), "txs", work.tcount, "special txs", len(specialTxs), "uncles", len(uncles), "elapsed", common.PrettyDuration(time.Since(tstart))) + log.Info("Committing new block", "number", work.Block.Number(), "txs", work.tcount, "special txs", len(specialTxs), "uncles", len(uncles), "elapsed", common.PrettyDuration(time.Since(tstart))) self.unconfirmed.Shift(work.Block.NumberU64() - 1) + self.lastParentBlockCommit = parent.Hash().Hex() } self.push(work) } @@ -634,7 +644,6 @@ func (env *Work) commitTransactions(mux *event.TypeMux, txs *types.TransactionsB gp := new(core.GasPool).AddGas(env.header.GasLimit) var coalescedLogs []*types.Log - // first priority for special Txs for _, tx := range specialTxs { if gp.Gas() < params.TxGas && tx.Gas() > 0 { @@ -654,6 +663,11 @@ func (env *Work) commitTransactions(mux *event.TypeMux, txs *types.TransactionsB } // Start executing the transaction env.state.Prepare(tx.Hash(), common.Hash{}, env.tcount) + nonce := env.state.GetNonce(from) + if nonce != tx.Nonce() { + log.Trace("Skipping account with special transaction invalide nonce", "sender", from, "nonce", nonce, "tx nonce ", tx.Nonce(), "to", tx.To()) + continue + } err, logs := env.commitTransaction(tx, bc, coinbase, gp) switch err { case core.ErrNonceTooLow: @@ -663,7 +677,6 @@ func (env *Work) commitTransactions(mux *event.TypeMux, txs *types.TransactionsB case core.ErrNonceTooHigh: // Reorg notification data race between the transaction pool and miner, skip account = log.Trace("Skipping account with special transaction hight nonce", "sender", from, "nonce", tx.Nonce(), "to", tx.To()) - case nil: // Everything ok, collect the logs and shift in the next transaction from the same account coalescedLogs = append(coalescedLogs, logs...) @@ -675,7 +688,6 @@ func (env *Work) commitTransactions(mux *event.TypeMux, txs *types.TransactionsB log.Debug("Add Special Transaction failed, account skipped", "hash", tx.Hash(), "sender", from, "nonce", tx.Nonce(), "to", tx.To(), "err", err) } } - for { // If we don't have enough gas for any further transactions then we're done if gp.Gas() < params.TxGas { @@ -696,13 +708,24 @@ func (env *Work) commitTransactions(mux *event.TypeMux, txs *types.TransactionsB // phase, start ignoring the sender until we do. if tx.Protected() && !env.config.IsEIP155(env.header.Number) { log.Trace("Ignoring reply protected transaction", "hash", tx.Hash(), "eip155", env.config.EIP155Block) - txs.Pop() continue } // Start executing the transaction env.state.Prepare(tx.Hash(), common.Hash{}, env.tcount) - + nonce := env.state.GetNonce(from) + if nonce > tx.Nonce() { + // New head notification data race between the transaction pool and miner, shift + log.Trace("Skipping transaction with low nonce", "sender", from, "nonce", tx.Nonce()) + txs.Shift() + continue + } + if nonce < tx.Nonce() { + // Reorg notification data race between the transaction pool and miner, skip account = + log.Trace("Skipping account with hight nonce", "sender", from, "nonce", tx.Nonce()) + txs.Pop() + continue + } err, logs := env.commitTransaction(tx, bc, coinbase, gp) switch err { case core.ErrGasLimitReached: @@ -717,7 +740,7 @@ func (env *Work) commitTransactions(mux *event.TypeMux, txs *types.TransactionsB case core.ErrNonceTooHigh: // Reorg notification data race between the transaction pool and miner, skip account = - log.Trace("Skipping account with hight nonce", "sender", from, "nonce", tx.Nonce()) + log.Trace("Skipping account with high nonce", "sender", from, "nonce", tx.Nonce()) txs.Pop() case nil: @@ -733,7 +756,6 @@ func (env *Work) commitTransactions(mux *event.TypeMux, txs *types.TransactionsB txs.Shift() } } - if len(coalescedLogs) > 0 || env.tcount > 0 { // make a copy, the state caches the logs and these logs get "upgraded" from pending to mined // logs by filling in the block hash when the block was mined by the local miner. This can diff --git a/node/config.go b/node/config.go index dda24583ee..cbc27317fa 100644 --- a/node/config.go +++ b/node/config.go @@ -147,6 +147,8 @@ type Config struct { // Logger is a custom logger to use with the p2p.Server. Logger log.Logger `toml:",omitempty"` + + AnnounceTxs bool `toml:",omitempty"` } // IPCEndpoint resolves an IPC endpoint based on a configured value, taking into diff --git a/params/version.go b/params/version.go index 6e2690c62d..02e09f535d 100644 --- a/params/version.go +++ b/params/version.go @@ -21,9 +21,9 @@ 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 + VersionMajor = 1 // Major version component of the current release + VersionMinor = 1 // Minor version component of the current release + VersionPatch = 0 // Patch version component of the current release VersionMeta = "stable" // Version metadata to append to the version string )