The Greenfield BSC Archiver is tasked with storing headers and bodies of BSC historical blocks. It uploads this block information to Greenfield via the bundle service. The components of this archiver include:
Responsible for fetching block information via Ethereum calls, storing it in a database, and uploading it to Greenfield through the bundle service. The current setting uploads data every 100 blocks.
Regularly checks the integrity of uploaded data on Greenfield. If errors are found, it corrects and re-uploads the data, and updates the block bundle name in the database.
Provides RPC interfaces compatible with Ethereum calls. Variables are generated using a Swagger.yaml file to ensure adaptability.
- eth_getBlockByNumber
- eth_getBundledBlockByNumber
- eth_blockNumber
- eth_getBlockByHash
- /bsc/v1/blocks/{block_id}/bundle/name
Network | Endpoint | Bucket |
---|---|---|
BSC | https://gnfd-bsc-archiver-mainnet.bnbchain.org/ | mainnet-bsc-blocks |
Method: POST URL: https://gnfd-bsc-archiver-mainnet.bnbchain.org/ eth_getBlockByNumber request
{
"method": "eth_getBlockByNumber",
"params": [
"0x1"
],
"id": 100,
"jsonrpc": "2.0"
}
response
{
"id": 100,
"jsonrpc": "2.0",
"result": {
"difficulty": "0x2",
"extraData": "0xd883010002846765746888676f312e31332e34856c696e757800000000000000924cd67a1565fdd24dd59327a298f1d702d6b7a721440c063713cecb7229f4e162ae38be78f6f71aa5badeaaef35cea25061ee2100622a4a1631a07e862b517401",
"gasLimit": "0x25ff7a7",
"gasUsed": "0x300b37",
"hash": "0x04055304e432294a65ff31069c4d3092ff8b58f009cdb50eba5351e0332ad0f6",
"logsBloom": "0x08000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000",
"miner": "0x2a7cdd959bFe8D9487B2a43B33565295a698F7e2",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0000000000000000",
"number": "0x1",
"parentHash": "0x0d21840abff46b96c84b2ac9e10e4f5cdaeb5693cb665db62a2f3b02d2d57b5b",
"receiptsRoot": "0xfc7c0fda97e67ed8ae06e7a160218b3df995560dfcb209a3b0dddde969ec6b00",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"size": "0x558",
"stateRoot": "0x1db428ea79cb2e8cc233ae7f4db7c3567adfcb699af668a9f583fdae98e95588",
"timestamp": "0x5f49ca59",
"totalDifficulty": "0x3",
"transactions": [
{
"blockHash": "0x04055304e432294a65ff31069c4d3092ff8b58f009cdb50eba5351e0332ad0f6",
"blockNumber": "0x1",
"chainId": "0x38",
"from": "0x2a7cdd959bFe8D9487B2a43B33565295a698F7e2",
"gas": "0x7fffffffffffffff",
"gasPrice": "0x0",
"hash": "0xbaf8ffa0b475a67cfeac3992d24422804452f0982e4e21a8816db2e0c9e5f224",
"input": "0xe1c7392a",
"nonce": "0x0",
"r": "0xba64c6614028e6f7fa4cf2b218719160b9850c591279218def6894586ab73157",
"s": "0x69cd1b3041eaa9b282a522c49b294e3c51801a1347bb8999015a0bd29bed3bbf",
"to": "0x0000000000000000000000000000000000001000",
"transactionIndex": "0x0",
"type": "0x0",
"v": "0x93",
"value": "0x0"
},
],
"transactionsRoot": "0x53a8743b873570daa630948b1858eaf5dc9bb0bca2093a197e507b2466c110a0",
"uncles": []
}
}
In scenarios where the Bundle Service is inaccessible, direct access to block data stored in Greenfield may be necessary, as blocks are consolidated into a bundle object. User can retrieve the bundle object and extract specific blocks from it.
The bundle objects uploaded to Greenfield adhere to the naming pattern blocks_s{startSlot}_e{endSlot}
. For instance, if a bundle encompasses blocks within 30 slots, the bundle object could be named blocks_s8864048_e8864077
, where 8864048 represents the start slot and 8864077 denotes the end slot. The individual blocks contained within this bundle follow the naming convention block_h{}
, such as block_h100
.
The bundle SDK offers commands to fetch the bundle object from Greenfield. Follow the steps below:
git submodule update --init --recursive
cd bundle-sdk && make build
./build/bundler download -bucket mainnet-bsc-blocks -object blocks_s6907440_e6907459 -chain-id greenfield_1017-1 -rpc-url https://greenfield-chain.bnbchain.org:443 -output ./tmp
Once the bundle is downloaded and extracted, all original block files can be found within the tmp
directory.
Go version above 1.22
if you don't have a bucket yet, set up one for block storage. There are a few ways to create one, below shows examples via greenfield-go-sdk and using provided script.
Visit https://dcellar.io/ and create a bucket with at least 100G read quota per month.
You can use the script, before runinng it, modify the the scripts/.env file(the GRANTEE_BUNDLE_ACCOUNT does not need to modified at this moment):
bash scripts/set_up.sh --create_bucket
Request a bundle account from the Bundle Service, you need to grant the bundle account permission in next step, so that bundle service can create object behave of your account.
curl -X POST https://gnfd-mainnet-bundle.nodereal.io/v1/bundlerAccount/0xf74d8897D8BeafDF4b766E19A62078DE84570656
{"address":"0x4605BFc98E0a5EA63D9D5a4a1Df549732a6963f3"}
package main
import (
"context"
"log"
"testing"
"cosmossdk.io/math"
"github.com/bnb-chain/greenfield-go-sdk/client"
"github.com/bnb-chain/greenfield-go-sdk/pkg/utils"
types3 "github.com/bnb-chain/greenfield-go-sdk/types"
types4 "github.com/bnb-chain/greenfield/sdk/types"
"github.com/bnb-chain/greenfield/x/permission/types"
types2 "github.com/cosmos/cosmos-sdk/types"
)
func TestClient_ListBuckets(t *testing.T) {
defaultAccount, _ := types3.NewAccountFromPrivateKey("barry", "private-key")
cli, _ := client.New("greenfield_5600-1", "https://gnfd-testnet-fullnode-tendermint-ap.bnbchain.org:443", client.Option{
DefaultAccount: defaultAccount,
})
bucketActions := []types.ActionType{types.ACTION_CREATE_OBJECT}
statements := utils.NewStatement(bucketActions, types.EFFECT_ALLOW, nil, types3.NewStatementOptions{
StatementExpireTime: nil,
LimitSize: 0,
})
bundleAgentPrincipal, err := utils.NewPrincipalWithAccount(types2.MustAccAddressFromHex("0x4605BFc98E0a5EA63D9D5a4a1Df549732a6963f3"))
if err != nil {
log.Fatalf("NewPrincipalWithAccount: %v", err)
return
}
_, err = cli.PutBucketPolicy(context.Background(), "your-bucket-name", bundleAgentPrincipal, []*types.Statement{&statements}, types3.PutPolicyOption{})
if err != nil {
log.Fatalf("put policy failed: %v", err)
return
}
allowanceAmount := math.NewIntWithDecimal(1, 19)
_, err = cli.GrantBasicAllowance(context.Background(), "granteeAddress", allowanceAmount, nil, types4.TxOption{})
if err != nil {
log.Fatalf("grant fee allowance failed: %v", err)
}
}
You can find similar example permission:
or you can use the script, replace GRANTEE_BUNDLE_ACCOUNT
with the addr got from Bundle Service in step 2, and modify the ALLOWANCE
to your expect amount, so that transacion
gas will be paid your account:
bash scripts/set_up.sh --grant
After above steps are done, you can start running the Greenfield BSC Archiver.
make build
make build_syncer
make build_server
./build/server --config-path config/local/config-server.json --port 8080