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

Release version 9.3.0 #789

Merged
merged 18 commits into from
Apr 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
- image: circleci/golang:1.13.4-browsers
- image: 0xorg/ganache-cli:istanbul
environment:
VERSION: 5.1.0
VERSION: 6.2.4
SNAPSHOT_NAME: 0x_ganache_snapshot
resource_class: large
steps:
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.


## v9.3.0

### Features ✅

- Mesh now ensures on startup that the chain ID of your Ethereum RPC endpoint matches config.EthereumChainID [#733](https://github.com/0xProject/0x-mesh/pull/733).

### Bug fixes 🐞

- Fixed a compatibility issue in `@0x/mesh-browser-lite` for Safari and some other browsers [#770](https://github.com/0xProject/0x-mesh/pull/770).
- Fixes an issue that would allow expired orders to be returned in `GetOrders` [773](http://github.com/0xProject/0x-mesh/pull/773)
- Fixed a rare bug where ERC721 approval events could be missed [#782](https://github.com/0xProject/0x-mesh/pull/782)


## v9.2.1

### Bug fixes 🐞
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-9.2.1-orange.svg)](https://github.com/0xProject/0x-mesh/releases)
[![Version](https://img.shields.io/badge/version-9.3.0-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
10 changes: 8 additions & 2 deletions RELEASE_CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
- [Docker image](https://hub.docker.com/r/0xorg/mesh/tags)
- [README](https://github.com/0xProject/0x-mesh/blob/v9.2.1/README.md)
- [README](https://github.com/0xProject/0x-mesh/blob/v9.3.0/README.md)

## Summary

### Features ✅

- Mesh now ensures on startup that the chain ID of your Ethereum RPC endpoint matches config.EthereumChainID [#733](https://github.com/0xProject/0x-mesh/pull/733).

### Bug fixes 🐞

- Fixed a critical bug in the ordersync protocol which resulted in only 50% of existing orders being shared when a new peer joins the network. New orders are shared separately and were unaffected. [#760](https://github.com/0xProject/0x-mesh/pull/760).
- Fixed a compatibility issue in `@0x/mesh-browser-lite` for Safari and some other browsers [#770](https://github.com/0xProject/0x-mesh/pull/770).
- Fixes an issue that would allow expired orders to be returned in `GetOrders` [773](http://github.com/0xProject/0x-mesh/pull/773)
- Fixed a rare bug where ERC721 approval events could be missed [#782](https://github.com/0xProject/0x-mesh/pull/782)



72 changes: 63 additions & 9 deletions cmd/cut-release/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import (
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"regexp"
"strings"

"github.com/plaid/go-envvar/envvar"
)

var functionDocsTemplate = "\n# Functions\n\n## loadMeshStreamingForURLAsync\n▸ **loadMeshStreamingWithURLAsync**(`url`: `string`): *Promise‹`void`›*\n\n*Defined in [index.ts:7](https://github.com/0xProject/0x-mesh/blob/%s/packages/browser-lite/src/index.ts#L7)*\n\nLoads the Wasm module that is provided by fetching a url.\n\n**Parameters:**\n\nName | Type | Description |\n------ | ------ | ------ |\n`url` | `string` | The URL to query for the Wasm binary |\n\n<hr />\n\n## loadMeshStreamingAsync\n\n▸ **loadMeshStreamingAsync**(`response`: `Response | Promise<Response>`): *Promise‹`void`›*\n\n*Defined in [index.ts:15](https://github.com/0xProject/0x-mesh/blob/%s/packages/browser-lite/src/index.ts#L15)*\n\nLoads the Wasm module that is provided by a response.\n\n**Parameters:**\n\nName | Type | Description |\n------ | ------ | ------ |\n`response` | `Response &#124; Promise<Response>` | The Wasm response that supplies the Wasm binary |\n\n<hr />"

type envVars struct {
// Version is the new release version to use
Version string `envvar:"VERSION"`
Expand All @@ -34,15 +37,7 @@ func main() {
log.Fatal(err)
}

// Generate documentation for the Typescript packages.
cmd = exec.Command("yarn", "docs:md")
cmd.Dir = "."
stdoutStderr, err = cmd.CombinedOutput()
if err != nil {
log.Print(string(stdoutStderr))
log.Fatal(err)
}

generateTypescriptDocs()
createReleaseChangelog(env.Version)
}

Expand All @@ -67,6 +62,49 @@ func createReleaseChangelog(version string) {
}
}

func generateTypescriptDocs() {
// Generate the initial docs for the Typescript packages. These docs will
// be used to create the final set of docs.
cmd := exec.Command("yarn", "docs:md")
cmd.Dir = "."
stdoutStderr, err := cmd.CombinedOutput()
if err != nil {
log.Print(string(stdoutStderr))
log.Fatal(err)
}
commitHash, err := getDocsCommitHash("docs/browser-bindings/browser-lite/reference.md")
if err != nil {
log.Fatal(err)
}

// Copy the browser-lite docs to the `@0x/mesh-browser` packages's `reference.md`
// file. These docs are the correct docs for the `@0x/mesh-browser` package.
cmd = exec.Command(
"cp",
"docs/browser-bindings/browser-lite/reference.md",
"docs/browser-bindings/browser/reference.md",
)
cmd.Dir = "."
stdoutStderr, err = cmd.CombinedOutput()
if err != nil {
log.Print(string(stdoutStderr))
log.Fatal(err)
}

// Create the documentation for the `loadMeshStreamingAsync` and the `loadMeshStreamingWithURLAsync`
// functions. Append these docs to the end of the existing browser-lite docs.
functionDocs := fmt.Sprintf(functionDocsTemplate, commitHash, commitHash)
f, err := os.OpenFile("docs/browser-bindings/browser-lite/reference.md",
os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatal(err)
}
defer f.Close()
if _, err := f.WriteString(functionDocs); err != nil {
log.Fatal(err)
}
}

// Update the version string in all files that must be updated for a new release
func updateHardCodedVersions(version string) {
// Update `packages/rpc-client/package.json`
Expand Down Expand Up @@ -134,6 +172,22 @@ func updateFileWithRegex(filePath string, regex string, replacement string) {
}
}

func getDocsCommitHash(docsPath string) (string, error) {
dat, err := ioutil.ReadFile(docsPath)
if err != nil {
log.Fatal(err)
}

regex := "https://github.com/0xProject/0x-mesh/blob/([a-f0-9]+)/"
var re = regexp.MustCompile(regex)
matches := re.FindStringSubmatch(string(dat))

if len(matches) < 2 {
return "", errors.New("No contents found")
}
return matches[1], nil
}

func getFileContentsWithRegex(filePath string, regex string) (string, error) {
dat, err := ioutil.ReadFile(filePath)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ var GanacheAccountToPrivateKey = map[common.Address][]byte{
var GanacheDummyERC721TokenAddress = common.HexToAddress("0x07f96aa816c1f244cbc6ef114bb2b023ba54a2eb")

// GanacheDummyERC1155MintableAddress is the dummy ERC1155 token address in the Ganache snapshot
var GanacheDummyERC1155MintableAddress = common.HexToAddress("0x8d42e38980ce74736c21c059b2240df09958d3c8")
var GanacheDummyERC1155MintableAddress = common.HexToAddress("0x038f9b392fb9a9676dbaddf78ea5fdbf6c7d9710")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this wrong before? I wasn't aware that we changed it's location in the migration script.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It did change with the updated snapshot we're now using (6.2.4). Prior to this version, we were on version 5.1.0. It must have changed sometime between those two versions.


// ErrInternal is used whenever we don't wish to expose internal errors to a client
var ErrInternal = errors.New("internal error")
Expand Down
143 changes: 102 additions & 41 deletions core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,28 @@ const (
estimatedNonPollingEthereumRPCRequestsPer24Hrs = 50000
// logStatsInterval is how often to log stats for this node.
logStatsInterval = 5 * time.Minute
version = "9.2.1"
version = "9.3.0"
// ordersyncMinPeers is the minimum amount of peers to receive orders from
// before considering the ordersync process finished.
ordersyncMinPeers = 5
paginationSubprotocolPerPage = 500
ordersyncMinPeers = 5
// ordersyncApproxDelay is the approximate amount of time to wait between each
// run of the ordersync protocol (as a requester). We always request orders
// immediately on startup. This delay only applies to subsequent runs.
ordersyncApproxDelay = 1 * time.Hour
)

// privateConfig contains some configuration options that can only be changed from
// within the core package. Intended for testing purposes.
type privateConfig struct {
paginationSubprotocolPerPage int
}

func defaultPrivateConfig() privateConfig {
return privateConfig{
paginationSubprotocolPerPage: 500,
}
}

// Note(albrow): The Config type is currently copied to browser/ts/index.ts. We
// need to keep both definitions in sync, so if you change one you must also
// change the other.
Expand Down Expand Up @@ -184,6 +199,7 @@ type snapshotInfo struct {

type App struct {
config Config
privateConfig privateConfig
peerID peer.ID
privKey p2pcrypto.PrivKey
node *p2p.Node
Expand All @@ -209,6 +225,10 @@ type App struct {
var setupLoggerOnce = &sync.Once{}

func New(config Config) (*App, error) {
return newWithPrivateConfig(config, defaultPrivateConfig())
}

func newWithPrivateConfig(config Config, pConfig privateConfig) (*App, error) {
// Configure logger
// TODO(albrow): Don't use global variables for log settings.
setupLoggerOnce.Do(func() {
Expand Down Expand Up @@ -389,6 +409,7 @@ func New(config Config) (*App, error) {
app := &App{
started: make(chan struct{}),
config: config,
privateConfig: pConfig,
privKey: privKey,
peerID: peerID,
chainID: config.EthereumChainID,
Expand Down Expand Up @@ -576,6 +597,27 @@ func (app *App) Start(ctx context.Context) error {
orderWatcherErrChan <- app.orderWatcher.Watch(innerCtx)
}()

// Ensure that RPC client is on the same ChainID as is configured with ETHEREUM_CHAIN_ID
chainIDMismatchErrChan := make(chan error, 1)
wg.Add(1)
go func() {
defer wg.Done()
defer func() {
log.Debug("closing chainID checker")
}()

chainID, err := app.getEthRPCChainID(innerCtx)
if err != nil {
chainIDMismatchErrChan <- err
return
}

configChainID := app.config.EthereumChainID
if int64(configChainID) != chainID.Int64() {
chainIDMismatchErrChan <- fmt.Errorf("ChainID mismatch between RPC client (chainID: %d) and configured environment variable ETHEREUM_CHAIN_ID: %d", chainID, configChainID)
}
}()

// Note: this is a blocking call so we won't continue set up until its finished.
blocksElapsed, err := app.blockWatcher.FastSyncToLatestBlock(innerCtx)
if err != nil {
Expand Down Expand Up @@ -648,7 +690,7 @@ func (app *App) Start(ctx context.Context) error {

// Register and start ordersync service.
ordersyncSubprotocols := []ordersync.Subprotocol{
NewFilteredPaginationSubprotocol(app, paginationSubprotocolPerPage),
NewFilteredPaginationSubprotocol(app, app.privateConfig.paginationSubprotocolPerPage),
}
app.ordersyncService = ordersync.New(innerCtx, app.node, ordersyncSubprotocols)
orderSyncErrChan := make(chan error, 1)
Expand All @@ -658,7 +700,13 @@ func (app *App) Start(ctx context.Context) error {
defer func() {
log.Debug("closing ordersync service")
}()
if err := app.ordersyncService.GetOrders(innerCtx, ordersyncMinPeers); err != nil {
log.WithFields(map[string]interface{}{
"approxDelay": ordersyncApproxDelay,
"perPage": app.privateConfig.paginationSubprotocolPerPage,
"subprotocols": []string{"FilteredPaginationSubProtocol"},
}).Info("starting ordersync service")

if err := app.ordersyncService.PeriodicallyGetOrders(innerCtx, ordersyncMinPeers, ordersyncApproxDelay); err != nil {
orderSyncErrChan <- err
}
}()
Expand Down Expand Up @@ -703,47 +751,60 @@ func (app *App) Start(ctx context.Context) error {
log.Info("core.App was started")
close(app.started)

// Wait for all other goroutines to close.
appClosed := make(chan struct{})
go func() {
wg.Wait()
close(appClosed)
}()

// If any error channel returns a non-nil error, we cancel the inner context
// and return the error. Note that this means we only return the first error
// that occurs.
select {
case err := <-p2pErrChan:
if err != nil {
log.WithError(err).Error("p2p node exited with error")
cancel()
return err
}
case err := <-orderWatcherErrChan:
if err != nil {
log.WithError(err).Error("order watcher exited with error")
cancel()
return err
}
case err := <-blockWatcherErrChan:
if err != nil {
log.WithError(err).Error("block watcher exited with error")
cancel()
return err
}
case err := <-ethRPCRateLimiterErrChan:
if err != nil {
log.WithError(err).Error("ETH JSON-RPC ratelimiter exited with error")
cancel()
return err
}
case err := <-orderSyncErrChan:
if err != nil {
log.WithError(err).Error("ordersync service exited with error")
cancel()
return err
for {
select {
case err := <-p2pErrChan:
if err != nil {
log.WithError(err).Error("p2p node exited with error")
cancel()
return err
}
case err := <-orderWatcherErrChan:
if err != nil {
log.WithError(err).Error("order watcher exited with error")
cancel()
return err
}
case err := <-blockWatcherErrChan:
if err != nil {
log.WithError(err).Error("block watcher exited with error")
cancel()
return err
}
case err := <-ethRPCRateLimiterErrChan:
if err != nil {
log.WithError(err).Error("ETH JSON-RPC ratelimiter exited with error")
cancel()
return err
}
case err := <-orderSyncErrChan:
if err != nil {
log.WithError(err).Error("ordersync service exited with error")
cancel()
return err
}
case err := <-chainIDMismatchErrChan:
if err != nil {
log.WithError(err).Error("ETH chain id matcher exited with error")
cancel()
return err
}
case <-appClosed:
// If we reached here it means we are done and there are no errors.
log.Debug("app successfully closed")
return nil
}
}

// Wait for all goroutines to exit. If we reached here it means we are done
// and there are no errors.
wg.Wait()
log.Debug("app successfully closed")
return nil
}

func (app *App) periodicallyCheckForNewAddrs(ctx context.Context, startingAddrs []ma.Multiaddr) {
Expand Down
Loading