Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tx/Common: Polygon PoS Chain Support #1289

Closed
holgerd77 opened this issue Jun 8, 2021 · 9 comments
Closed

Tx/Common: Polygon PoS Chain Support #1289

holgerd77 opened this issue Jun 8, 2021 · 9 comments

Comments

@holgerd77
Copy link
Member

Part of #1288

Polygon is a protocol and framework for building Ethereum compatible networks which gained a lot of traction lately. Note that the dedicated chains are named differently from the protocol, there is e.g. the Polygon PoS Chain (this is the main one I guess?).

We should test if we can get a connection going with the tx library respectively the underlying common library and ultimately send a transaction and doing an according PR on the libraries. If setting up a connection is not possible with our current library structure we should alternatively mention in the tx README.

@ryanio
Copy link
Contributor

ryanio commented Jun 8, 2021

I will give this a try later today :)

@ryanio
Copy link
Contributor

ryanio commented Jun 9, 2021

Cool news, so Matic has a Mumbai testnet which extends goerli, so with a custom common I was able to send eth_sendRawTransaction to the rpc endpoint and it got confirmed within seconds.

const customChainParams = { name: 'matic-mumbai', chainId: 80001, networkId: 80001 }
const common = Common.forCustomChain('goerli', customChainParams)

I used our test dev account: 0xaaec86394441f915bce3e6ab399977e9906f3b69, funded it with 0.1 MATIC (native chain currency) from the faucet, then sent out some txs with this test script I was using a few weeks ago to bombard baikal 😄

const http = require('http')
import { Transaction } from '../ethereumjs-monorepo/packages/tx/src'
import Common from '../ethereumjs-monorepo/packages/common/dist'

const FROM = '0xaaec86394441f915bce3e6ab399977e9906f3b69'
const to = '0xe13ece23b514caa5b53395c01d0d53d1843258ad'

const customChainParams = { name: 'matic-mumbai', chainId: 80001, networkId: 80001 }
const common = Common.forCustomChain('goerli', customChainParams) as any

const txData = {
    nonce: 3,
    gasPrice: 20000000000,
    gasLimit: 210000,
    to,
    value: 100,
    data: '0x',
}

const start = async () => {
    for (let i = 0; i < 1; i++) {
        const tx = Transaction.fromTxData({ ...txData, nonce: txData.nonce + i }, { common })
        const signedTx = tx.sign(Buffer.from(PRIV_KEY, 'hex'))
        const rawTx = '0x' + signedTx.serialize().toString('hex')
        const data = JSON.stringify(
            { "jsonrpc": "2.0", "method": "eth_sendRawTransaction", "params": [rawTx], "id": 1 }
        )
        console.log('Sending tx with nonce ' + tx.nonce.toString())
        sendReq(data)
        await timeout(2000)
    }
}

start()

function timeout(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

function sendReq(data) {
    const options = {
        hostname: 'rpc-mumbai.matic.today',
        path: '/',
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Content-Length': data.length
        }
    }
    const req = http.request(options, res => {
        console.log(`statusCode: ${res.statusCode}`)
        res.on('data', d => {
            process.stdout.write(d + '\n')
        })
    })
    req.on('error', error => {
        console.error(error)
    })
    req.write(data)
    req.end()
}

@holgerd77
Copy link
Member Author

Pretty cool. 😀 🎉

@holgerd77
Copy link
Member Author

@ryanio I am not quite sure yet what to do with these first results (also with the Arbitrum example).

We could:

a) Simply add a section to the docs adding the networks we have confirmed
b) Use an existing API method to simplify a bit, e.g. also allow string input in forCustomChain() for selected networks for customChainParams and then allow something like forCustomChain('goerli', 'matic-mumbai') and internally do a recursive call to the same method with the chain ID added
c) add a new dedicated static constructor for these predefined lightweight initalizations
d) do nothing for now and investigate this a bit further

Any idea? Do you already have got some picture about the HF situation on these L2 solutions? Would the hardfork files as we have them for the L1 chains also be useful for the L2 chains? Also not sure if we can then do anything with this information. It's likely not realistic to target client sync on any of these chains (or is it?). Maybe tx execution in the VM is the closest use case for some? Not sure.

@holgerd77
Copy link
Member Author

My current favorite: we add a dedicated new class of static factory method for all networks where there is still some kind of limited support, naming suggestion would be forCustomSupportedChain('matic-mumbai'), and we explicitly document this "Chains supported by this method have a limited functionality set, minimally providing the chain ID of the network. These chains will likely not run in the VM but can be used for selected use cases (e.g. sending txs to a supported L2 network)".

We can then internally call forCustomChain(), with setting the chainId and passing over the name and eventually adding other parameters over time.

It is also still possible to eventually switch over at some point to add the whole chain as a chain file to give full Common support without these limitations.

@holgerd77
Copy link
Member Author

For reference: Ethers just also added Matic support with this commit.

@Neozaru
Copy link

Neozaru commented Jun 21, 2021

Hello.
I am trying to get this working with sendSignedTransaction. Using an existing code I was using for mainnet and ropsten, my custom chain descriptor is as follows:

const etxOptions = forCustomChain(
    'goerli',
    {
      name: 'matic-mumbai',
      networkId: 80001,
      chainId: 80001
    },
    'muirGlacier'
  )

I then use Transaction.fromTxData(txParams, etxOptions) where txParams has a chainId parameter set to 80001 (or hex equivalent, tried both - not sure this param is required).
Signing, then serializing before sending using sendSignedTransaction, I get the following as a response:
Returned error: only replay-protected (EIP-155) transactions allowed over RPC
This is using Infura Polygon (mumbai) endpoint. It looks like the issue is that the chainId is not properly incorporated in the signed transaction (?), which I am not sure if it should have been handled transparently by Transaction.fromTxData or there is any particular action I should do - I though that was done automatically.

@holgerd77
Copy link
Member Author

Two things I am seeing from this code and your description, which might be problematic (a bit hard to analyze, a somewhat more complete code example would have been helpful, but maybe that's already it):

  1. extOptions - as you call it - is a Common instance and needs to be passed in via the common options dict parameter with Transaction.fromTxData(txParams, { common: etxOptions}) (you might want to choose a better name for extOptions, probably just common
  2. When signing the tx with tx.sign() the original tx is not signed but a new signed tx is returned the function, so you have to do: const signedTx = tx.sign()

Hope this helps. 😄

@holgerd77 holgerd77 changed the title Tx: Polygon PoS Chain Support Tx/Common: Polygon PoS Chain Support Jun 28, 2021
@ryanio
Copy link
Contributor

ryanio commented Jul 19, 2021

Added in #1317

@ryanio ryanio closed this as completed Jul 19, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants