infura / go-ethlibs Goto Github PK
View Code? Open in Web Editor NEWEthereum libraries in Go for interacting with Ethereum nodes
License: MIT License
Ethereum libraries in Go for interacting with Ethereum nodes
License: MIT License
I mentioned this as a comment in #18, but ideally we don't change the outgoing request ID in the websocket/IPC layer unless strictly necessary. However, to do this either the clients need to ensure that each concurrent request has a unique ID, or we need to serialize requests w/ the same ID, which requires a fair amount more logic in loop.go.
A good compromise after #7 is fixed is that if the context has no request ID, then generate a unique one, if the context has an ID, first see if there's already a request w/ that ID in flight, in which case we need to wait for that previous request to complete before dispatching the next one.
Thus, by default, the client would behave as it does now: each request gets it's own auto-generated unique ID. If a client wants to both control IDs and dispatch multiple requests concurrently, they need to supply unique IDs to each request, which seems like a reasonable trade-off.
Related to #36 we will need to support adding accessList
to eth.Transaction
when .Type
is eth.TransactionTypeAccessList
.
Not directly related to #61, but we could also simplify with the TextMarshaler
and TextUnmarshaler
interface, so we don't have to deal with json.Marshal/Unmarshal in our functions for the base64 encoding/decoding.
Those text marshalers would focus solely on validating and returning a canonical representation of an address, which would be compatible with other encoding formats.
Before
func (a *Address) UnmarshalJSON(data []byte) error {
// We'll keep the checksummed string in memory so we can use it for internal representations
str, err := unmarshalHex(data, 20, "data")
str = ToChecksumAddress(str)
if err != nil {
return err
}
*a = Address(str)
return nil
}
func (a Address) MarshalJSON() ([]byte, error) {
// Seems like geth and parity both return the lower-cased string rather than the checksummed one
s := strings.ToLower(string(a))
return json.Marshal(&s)
}
After
func (a *Address) UnmarshalText(text []byte) error {
str, err := validateHex(string(text), 20, "data")
if err != nil {
return err
}
str = ToChecksumAddress(str)
*a = Address(str)
return nil
}
func (a Address) MarshalText() ([]byte, error) {
return bytes.ToLower([]byte(a)), nil
}
Originally posted by @basgys in #61 (comment)
Push the multi-transport-client
branch and re-open here?
https://eips.ethereum.org/EIPS/eip-4844#header-extension
The current header encoding is extended with two new 64-bit unsigned integer fields:
blob_gas_used
is the total amount of blob gas consumed by the transactions within the block.excess_blob_gas
is a running total of blob gas consumed in excess of the target, prior to the block. Blocks with above-target blob gas consumption increase this value, blocks with below-target blob gas consumption decrease it (bounded at 0).Line 18 in 61f7907
For example this code pointed to a yolov3x node never returns from BlockByNumber
:
func main() {
ctx := context.Background()
url := "~/Library/Ethereum/yolo-v3/geth.ipc"
client, err := node.NewClient(ctx, url)
if err != nil {
panic(err)
}
start := uint64(0x3ede)
log.Printf("[WARN] start: %d", start)
block, err := client.BlockByNumber(ctx, start, true)
if err != nil {
panic(err)
} else {
log.Printf("[INFO] block: %#v", *block)
}
}
Haven't full debugged it but my guess is either the scanner fails and we don't handle the error correctly or the scanner hangs.
I have some boilerplate travisci already defined, so Travis works.
Some people like circleci, which I'm open to as well.
Please enable integration with one of them. :) (Assigning to people with permissions)
Now that Infura is predominately using geth 1.9.x for our backend nodes, I'd like to consider exposing EIP-1898
support, and adding it here seems like a good first step.
I'm picturing something like:
type Tag string //also update eth.BlockNumberOrTag to use this
type BlockSpecifier struct {
Number *Quantity
Tag *Tag
Hash *Hash
RequireCanonical *bool
Raw bool
}
And custom JSON (un)marshal routines that can handle the various cases:
.Raw
can be used when constructing a BlockSpecifier in code to control how it'll be marshaled, if true
then the specifier would be marshaled as a simple string instead of a JSON object (e.g. { Tag: Tag("latest") }
would be just "latest"
and not { "blockNumber": "latest" }
.
If anyone has objections or concerns, last chance to voice them here. :)
Things we'll want to do, as part of making the repo public:
make zz_deepcopy_generated.go
produces changes?Thinking about #7 more, and my general unhappiness with the verbosity of the node.Client
interface, it might make more sense to remove all the RPC-specific methods from that interface, and instead offer them as some sort of request builder and response parser pair.
So instead of:
block, err := client.BlockByHash(ctx, hash, true, node.WithRequestID(jsonrpc.ID{Str: "foo"}))
One would instead use:
block, err := pkg.NewRequest().BlockByHash(hash, true).WithStringID("foo").Send(client).Response().AsBlock()
Though not sure where said builders would live (e.g. what the actual name of pkg
would be).
This pattern is used in a couple places to varying effectiveness, namely go-redis and the golang AWS SDK v2. Anyways, just a rough idea for now, but the main advantage is that it separates the definition of new RPCs from node.Client
, which just needs to implement .Request
and .Subscribe
which makes implementing new virtual clients and or mocks much cleaner.
I'm assuming that this will also show up in eth.Block
since it's part of the RLP of the block header.
https://eips.ethereum.org/EIPS/eip-4788
execution-api tracking issue: ethereum/execution-apis#449
# curl https://rpc.dencun-devnet-8.ethpandaops.io/ -H 'Content-Type: application/json' -d '{"method":"eth_getBlockByNumber","params":["0x2a1cb", true],"id":1,"jsonrpc":"2.0"}' | jq .
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"baseFeePerGas": "0x7",
"blobGasUsed": "0x60000",
"difficulty": "0x0",
"excessBlobGas": "0x0",
"extraData": "0x4e65746865726d696e64",
"gasLimit": "0x1c9c380",
"gasUsed": "0xf618",
"hash": "0xfc2715ff196e23ae613ed6f837abd9035329a720a1f4e8dce3b0694c867ba052",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": "0xf97e180c050e5ab072211ad2c213eb5aee4df134",
"mixHash": "0xfe22e918a42ab40a176372da0352271d7a8d206af1f0f81b4ae24e0366b294e1",
"nonce": "0x0000000000000000",
"number": "0x2a1cb",
+ "parentBeaconBlockRoot": "0x3e75ca617f5191780dc90f5054d192c29167813ca0e38b84b26c30ae8886998b",
"parentHash": "0x0efbec3f110f71016eabe050984405a0f5b5bf7d4c653aaeb876a2a83d7e2a95",
"receiptsRoot": "0x9af165447e5b3193e9ac8389418648ee6d6cb1d37459fe65cfc245fc358721bd",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"size": "0x437",
"stateRoot": "0x4662ac8f239eb6b068a89d82db55fbd699bc883a43812a6ced13976f91c30b71",
"timestamp": "0x65004480",
"totalDifficulty": "0x1",
"transactions": [
{
"blockHash": "0xfc2715ff196e23ae613ed6f837abd9035329a720a1f4e8dce3b0694c867ba052",
"blockNumber": "0x2a1cb",
"from": "0xad01b55d7c3448b8899862eb335fbb17075d8de2",
"gas": "0x5208",
"gasPrice": "0x1d1a94a201c",
"maxFeePerGas": "0x1d1a94a201c",
"maxPriorityFeePerGas": "0x1d1a94a201c",
"maxFeePerBlobGas": "0x3e8",
"hash": "0x5ceec39b631763ae0b45a8fb55c373f38b8fab308336ca1dc90ecd2b3cf06d00",
"input": "0x",
"nonce": "0x1b483",
"to": "0x000000000000000000000000000000000000f1c1",
"transactionIndex": "0x0",
"value": "0x0",
"type": "0x3",
"accessList": [],
"chainId": "0x1a1f0ff42",
"blobVersionedHashes": [
"0x01a128c46fc61395706686d6284f83c6c86dfc15769b9363171ea9d8566e6e76"
],
"v": "0x0",
"r": "0x343c6239323a81ef61293cb4a4d37b6df47fbf68114adb5dd41581151a077da1",
"s": "0x48c21f6872feaf181d37cc4f9bbb356d3f10b352ceb38d1c3b190d749f95a11b",
"yParity": "0x0"
},
{
"blockHash": "0xfc2715ff196e23ae613ed6f837abd9035329a720a1f4e8dce3b0694c867ba052",
"blockNumber": "0x2a1cb",
"from": "0xad01b55d7c3448b8899862eb335fbb17075d8de2",
"gas": "0x5208",
"gasPrice": "0x1d1a94a201c",
"maxFeePerGas": "0x1d1a94a201c",
"maxPriorityFeePerGas": "0x1d1a94a201c",
"maxFeePerBlobGas": "0x3e8",
"hash": "0xed2587d8c4cccd09bc2c0ac50dd0bc596177b3eef2624957114fd8c075ff71f7",
"input": "0x",
"nonce": "0x1b484",
"to": "0x000000000000000000000000000000000000f1c1",
"transactionIndex": "0x1",
"value": "0x0",
"type": "0x3",
"accessList": [],
"chainId": "0x1a1f0ff42",
"blobVersionedHashes": [
"0x01f79951ba3a9c2a617bece3d0a355a32c21d2502b5d1245dcef954c1e97e301"
],
"v": "0x0",
"r": "0x1bffc7230fbf4675f4050ddfc09a0ea8957f6ed839f2a6aafe8d60ba3704f0a6",
"s": "0x42cf198e98b71eb47ab04b3115bb96de8ca8ee36ed92990efc258a0f80f4fa98",
"yParity": "0x0"
},
{
"blockHash": "0xfc2715ff196e23ae613ed6f837abd9035329a720a1f4e8dce3b0694c867ba052",
"blockNumber": "0x2a1cb",
"from": "0xad01b55d7c3448b8899862eb335fbb17075d8de2",
"gas": "0x5208",
"gasPrice": "0x1d1a94a201c",
"maxFeePerGas": "0x1d1a94a201c",
"maxPriorityFeePerGas": "0x1d1a94a201c",
"maxFeePerBlobGas": "0x3e8",
"hash": "0x8b6536d1dacf8f2e4d95bb8b2ed05067b96b27a8b3abe004d29a712cafdf712a",
"input": "0x",
"nonce": "0x1b485",
"to": "0x000000000000000000000000000000000000f1c1",
"transactionIndex": "0x2",
"value": "0x0",
"type": "0x3",
"accessList": [],
"chainId": "0x1a1f0ff42",
"blobVersionedHashes": [
"0x017c8f97daa97f4089502ff59f05e40217f2644a9462588189c5ca4e24221d08"
],
"v": "0x0",
"r": "0x8146d689e09836b87d4fe551cc590c83f6c96029f8def92686bfd1859fed4704",
"s": "0x4357b7bc331e23381841b6afc98cf4bd322cd6d90dd9f2f1af78b593611c7251",
"yParity": "0x0"
}
],
"transactionsRoot": "0xc5f62b8c7d89e8dce123a91ebe4fd2428f9960f13316e99ff4a8754bd8ee6fa8",
"uncles": [],
"withdrawals": [],
"withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
}
}
We need to be able to decode EIP-2930 RLP-encoded transactions in eth.Transaction.FromRaw
, as well as creating new signed EIP-2930 transactions in eth.Transaction.Sign
and eth.Transaction.RLP
.
More broadly, we need to be setup to handle EIP-2718 typed transactions in this code base.
Importantly we'll need to know how the RPC payloads change so we can deserialize e.g. eth_getTransactionByHash
on these txs into eth.Transaction
.
Once the JSONRPC format changes are settled on for EIP-2718, we will need to update eth.Transaction
and eth.TransactionReceipt
to include them. See https://gist.github.com/ryanschneider/723d8e2bce0829de9d6beb43639b6d3e for preliminary discussion on changes.
I can see some scenarios where the caller wants to provide an explicit JSONRPC request ID, but we currently don't expose that.
One solution would be in the GetBlockByNumber
, etc. methods in the websocket.Connection
interface took options as the last argument(s) (as varargs), and we provided a way to specify the request ID in those options. I can't think of any other options we'd want to implement right now, but could see us exposing options to configure the underlaying http or websocket requests (e.g. http headers or timeouts).
https://eips.ethereum.org/EIPS/eip-4844#blob-transaction
We introduce a new EIP-2718 transaction, “blob transaction”, where the TransactionType is BLOB_TX_TYPE
(0x03) and the TransactionPayload
is the RLP serialization of the following TransactionPayloadBody
:
[chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to, value, data, access_list, max_fee_per_blob_gas, blob_versioned_hashes, y_parity, r, s]
The field to
deviates slightly from the semantics with the exception that it MUST NOT be nil and therefore must always represent a 20-byte address. This means that blob transactions cannot have the form of a create transaction.
The field max_fee_per_blob_gas
is a uint256 and the field blob_versioned_hashes
represents a list of hash outputs from kzg_to_versioned_hash.
The EIP-2718 ReceiptPayload for this transaction is rlp([status, cumulative_transaction_gas_used, logs_bloom, logs])
.
If EIP-2711 is approved we'll want to add support in transaction.go
, transaction_from_raw.go
and transaction_signing.go
.
Line 33 in 8b8f17d
We should either make it *Quantity
or perhaps support omitempty
on Quantity
fields, not sure which is better yet, probably *Quantity
is more correct but is a breaking change.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.