Skip to content
This repository has been archived by the owner on Oct 11, 2024. It is now read-only.

Commit

Permalink
Merge pull request #690 from 0xProject/rebase/7.1.0-beta-new
Browse files Browse the repository at this point in the history
Backport Release 7.1.0-beta (0x V2 Mesh)
  • Loading branch information
fabioberger authored Jan 30, 2020
2 parents 07530fb + 2529023 commit 8cd82a9
Show file tree
Hide file tree
Showing 18 changed files with 811 additions and 478 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ jobs:
BASH_ENV: ~/.nvm/nvm.sh
docker:
- image: circleci/golang:1.12.13-browsers
- image: 0xorg/ganache-cli:latest
- image: 0xorg/ganache-cli:4.3.0
environment:
VERSION: 4.3.3
resource_class: large
Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@

This changelog is a work in progress and may contain notes for versions which have not actually been released. Check the [Releases](https://github.com/0xProject/0x-mesh/releases) page to see full release notes and more information about the latest released versions.

## v7.1.0-beta

### Features ✅

- Reduce startup time for Mesh node by only waiting for a block to be processed if Mesh isn't already sync'ed up to the latest block. ([#622](https://github.com/0xProject/0x-mesh/pull/622))
- Developers can now override the contract addresses for any testnet using the `CUSTOM_CONTRACT_ADDRESSES` env config ([#640](https://github.com/0xProject/0x-mesh/pull/640)).
- Add `getOrdersForPageAsync` method to `@0x/mesh-rpc-client` WS client interface so that clients can paginate through the retrieved orders themselves ([#642](https://github.com/0xProject/0x-mesh/pull/642)).

### Bug fixes 🐞

- Fixed a bug where we attempted to update the same order multiple times in a single DB txn, causing the later update to noop. ([#623](https://github.com/0xProject/0x-mesh/pull/623)).
- Fixed a bug which could cause Mesh to exit if a re-org condition occurs causing a block to be added and removed within the same block sync operation. ([#614](https://github.com/0xProject/0x-mesh/pull/614)).
- Fix bug where we attempted to update the same order multiple times in a single DB txn, causing the later update to noop. ([#623](https://github.com/0xProject/0x-mesh/pull/623))

## v7.0.0-beta

### Breaking changes 🛠
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[![Version](https://img.shields.io/badge/version-7.0.1--beta-orange.svg)](https://github.com/0xProject/0x-mesh/releases)
[![Version](https://img.shields.io/badge/version-7.1.0--beta-orange.svg)](https://github.com/0xProject/0x-mesh/releases)
[![Docs](https://img.shields.io/badge/docs-website-yellow.svg)](https://0x-org.gitbook.io/mesh)
[![Chat with us on Discord](https://img.shields.io/badge/chat-Discord-blueViolet.svg)](https://discord.gg/HF7fHwk)
[![Circle CI](https://img.shields.io/circleci/project/0xProject/0x-mesh/master.svg)](https://circleci.com/gh/0xProject/0x-mesh/tree/master)
Expand Down
2 changes: 1 addition & 1 deletion browser/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@0x/mesh-browser",
"version": "7.0.1-beta",
"version": "7.1.0-beta",
"description": "TypeScript and JavaScript bindings for running Mesh directly in the browser.",
"main": "./lib/index.js",
"license": "Apache-2.0",
Expand Down
43 changes: 35 additions & 8 deletions core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const (
estimatedNonPollingEthereumRPCRequestsPer24Hrs = 50000
// logStatsInterval is how often to log stats for this node.
logStatsInterval = 5 * time.Minute
version = "7.0.1-beta"
version = "7.1.0-beta"
)

// Note(albrow): The Config type is currently copied to browser/ts/index.ts. We
Expand Down Expand Up @@ -126,14 +126,15 @@ type Config struct {
// is typically only needed for testing on custom chains/networks. The given
// addresses are added to the default list of addresses for known chains/networks and
// overriding any contract addresses for known chains/networks is not allowed. The
// addresses for exchange, devUtils, erc20Proxy, and erc721Proxy are required
// addresses for exchange, devUtils, erc20Proxy, erc721Proxy and erc1155Proxy are required
// for each chain/network. For example:
//
// {
// "exchange":"0x48bacb9266a570d521063ef5dd96e61686dbe788",
// "devUtils": "0x38ef19fdf8e8415f18c307ed71967e19aac28ba1",
// "erc20Proxy": "0x1dc4c1cefef38a777b15aa20260a54e584b16c48",
// "erc721Proxy": "0x1d7022f5b17d2f8b695918fb48fa1089c9f85401"
// "erc721Proxy": "0x1d7022f5b17d2f8b695918fb48fa1089c9f85401",
// "erc1155Proxy": "0x64517fa2b480ba3678a2a3c0cf08ef7fd4fad36f"
// }
//
CustomContractAddresses string `envvar:"CUSTOM_CONTRACT_ADDRESSES" default:""`
Expand Down Expand Up @@ -464,11 +465,14 @@ func (app *App) Start(ctx context.Context) error {
blockWatcherErrChan <- app.blockWatcher.Watch(innerCtx)
}()

// Ensure orderWatcher has processed at least one recent block before
// starting the P2P node and completing app start, so that Mesh does
// not validate any orders at outdated block heights
if err := app.orderWatcher.WaitForAtLeastOneBlockToBeProcessed(ctx); err != nil {
return err
// If Mesh is not caught up with the latest block found via Ethereum RPC, ensure orderWatcher
// has processed at least one recent block before starting the P2P node and completing app start,
// so that Mesh does not validate any orders at outdated block heights
isCaughtUp := app.IsCaughtUpToLatestBlock(innerCtx)
if !isCaughtUp {
if err := app.orderWatcher.WaitForAtLeastOneBlockToBeProcessed(ctx); err != nil {
return err
}
}

if blocksElapsed >= constants.MaxBlocksStoredInNonArchiveNode {
Expand Down Expand Up @@ -906,6 +910,29 @@ func (app *App) SubscribeToOrderEvents(sink chan<- []*zeroex.OrderEvent) event.S
return subscription
}

// IsCaughtUpToLatestBlock returns whether or not the latest block stored by Mesh corresponds
// to the latest block retrieved from it's Ethereum RPC endpoint
func (app *App) IsCaughtUpToLatestBlock(ctx context.Context) bool {
latestBlockStored, err := app.db.FindLatestMiniHeader()
if err != nil {
if _, ok := err.(meshdb.MiniHeaderCollectionEmptyError); ok {
return false
}
log.WithFields(map[string]interface{}{
"err": err.Error(),
}).Warn("failed to fetch the latest miniHeader from DB")
return false
}
latestBlock, err := app.ethRPCClient.HeaderByNumber(ctx, nil)
if err != nil {
log.WithFields(map[string]interface{}{
"err": err.Error(),
}).Warn("failed to fetch the latest block header via Ethereum RPC")
return false
}
return latestBlock.Number.Cmp(latestBlockStored.Number) == 0
}

func parseAndAddCustomContractAddresses(chainID int, encodedContractAddresses string) error {
customAddresses := ethereum.ContractAddresses{}
if err := json.Unmarshal([]byte(encodedContractAddresses), &customAddresses); err != nil {
Expand Down
22 changes: 16 additions & 6 deletions db/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,28 @@ package db

import (
"errors"
"fmt"
"sync"
"sync/atomic"

"github.com/albrow/stringset"
)

var (
ErrDiscarded = errors.New("transaction has already been discarded")
ErrCommitted = errors.New("transaction has already been committed")
ErrConflictingOperations = errors.New("cannot perform more than one operation (insert/delete/update) on the same model within a transaction")
ErrDiscarded = errors.New("transaction has already been discarded")
ErrCommitted = errors.New("transaction has already been committed")
)

// ConflictingOperationsError is returned when two conflicting operations are attempted within the same
// transaction
type ConflictingOperationsError struct {
operation string
}

func (e ConflictingOperationsError) Error() string {
return fmt.Sprintf("error on %s: cannot perform more than one operation on the same model within a transaction", e.operation)
}

// Transaction is an atomic database transaction for a single collection which
// can be used to guarantee consistency.
type Transaction struct {
Expand Down Expand Up @@ -139,7 +149,7 @@ func (txn *Transaction) Insert(model Model) error {
return err
}
if txn.affectedIDs.Contains(string(model.ID())) {
return ErrConflictingOperations
return ConflictingOperationsError{operation: "insert"}
}
if err := insertWithTransaction(txn.colInfo, txn.readWriter, model); err != nil {
return err
Expand All @@ -159,7 +169,7 @@ func (txn *Transaction) Update(model Model) error {
return err
}
if txn.affectedIDs.Contains(string(model.ID())) {
return ErrConflictingOperations
return ConflictingOperationsError{operation: "update"}
}
if err := updateWithTransaction(txn.colInfo, txn.readWriter, model); err != nil {
return err
Expand All @@ -178,7 +188,7 @@ func (txn *Transaction) Delete(id []byte) error {
return err
}
if txn.affectedIDs.Contains(string(id)) {
return ErrConflictingOperations
return ConflictingOperationsError{operation: "delete"}
}
if err := deleteWithTransaction(txn.colInfo, txn.readWriter, id); err != nil {
return err
Expand Down
10 changes: 5 additions & 5 deletions db/transaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ func TestTransactionDeleteThenInsertSameModel(t *testing.T) {
require.NoError(t, txn.Delete(model.ID()))
err = txn.Insert(model)
assert.Error(t, err)
assert.Equal(t, ErrConflictingOperations, err, "wrong error")
assert.Equal(t, ConflictingOperationsError{operation: "insert"}, err, "wrong error")
}

func TestTransactionInsertThenDeleteSameModel(t *testing.T) {
Expand All @@ -309,7 +309,7 @@ func TestTransactionInsertThenDeleteSameModel(t *testing.T) {
require.NoError(t, txn.Insert(model))
err = txn.Delete(model.ID())
assert.Error(t, err)
assert.Equal(t, ErrConflictingOperations, err, "wrong error")
assert.Equal(t, ConflictingOperationsError{operation: "delete"}, err, "wrong error")
}

func TestTransactionInsertThenInsertSameModel(t *testing.T) {
Expand All @@ -334,7 +334,7 @@ func TestTransactionInsertThenInsertSameModel(t *testing.T) {
require.NoError(t, txn.Insert(model))
err = txn.Insert(model)
assert.Error(t, err)
assert.Equal(t, ErrConflictingOperations, err, "wrong error")
assert.Equal(t, ConflictingOperationsError{operation: "insert"}, err, "wrong error")
}

func TestTransactionDeleteThenDeleteSameModel(t *testing.T) {
Expand All @@ -360,7 +360,7 @@ func TestTransactionDeleteThenDeleteSameModel(t *testing.T) {
require.NoError(t, txn.Delete(model.ID()))
err = txn.Delete(model.ID())
assert.Error(t, err)
assert.Equal(t, ErrConflictingOperations, err, "wrong error")
assert.Equal(t, ConflictingOperationsError{operation: "delete"}, err, "wrong error")
}

func TestTransactionInsertThenUpdateSameModel(t *testing.T) {
Expand All @@ -385,5 +385,5 @@ func TestTransactionInsertThenUpdateSameModel(t *testing.T) {
require.NoError(t, txn.Insert(model))
err = txn.Update(model)
assert.Error(t, err)
assert.Equal(t, ErrConflictingOperations, err, "wrong error")
assert.Equal(t, ConflictingOperationsError{operation: "update"}, err, "wrong error")
}
Loading

0 comments on commit 8cd82a9

Please sign in to comment.