diff --git a/.github/workflows/docker-build.yaml b/.github/workflows/docker-build.yaml index 0cda6f3e3..55bbc14f9 100644 --- a/.github/workflows/docker-build.yaml +++ b/.github/workflows/docker-build.yaml @@ -5,21 +5,20 @@ on: tags: - v* push: - branches: [ netmarble_v1.0 ] + branches: [ netmarble_v1.0, netmarble_v2.0 ] pull_request: - branches: [ netmarble_v1.0 ] + branches: [ netmarble_v1.0, netmarble_v2.0 ] env: REGION: us-east-1 ECR_REGISTRY_ID: 553885929720 - AWS_ASSUMED_ROLE_ARN: arn:aws:iam::553885929720:role/tf_nodereal_prod_ecr_cicd_deployment_assume_role # Notice: must modify here to fit your service config path GIT_SYNC_PATH: qa/gitops/qa-us/demo-app/values.yaml TAG_FIELD: .image.tag jobs: CI: - runs-on: [self-hosted,qa-infra-k8s] + runs-on: [self-hosted,prod-cicd-runners] steps: - uses: actions/checkout@v3 # - uses: actions/setup-go@v3 @@ -30,25 +29,14 @@ jobs: # with: # # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version # version: v1.45.2 - - name: aws assume role - id: aws-assume-role - run: | - UUID=$(cat /proc/sys/kernel/random/uuid) - OUT=$(aws sts assume-role --role-arn $AWS_ASSUMED_ROLE_ARN --role-session-name $UUID) - echo ::set-output name=aws_access_key_id::"$(echo $OUT | jq -r '.Credentials''.AccessKeyId')" - echo ::set-output name=aws_secret_key::"$(echo $OUT | jq -r '.Credentials''.SecretAccessKey')" - echo ::set-output name=aws_sessions_token::"$(echo $OUT | jq -r '.Credentials''.SessionToken')" - name: Build, tag, and push image to Amazon ECR - env: - AWS_ACCESS_KEY_ID: ${{ steps.aws-assume-role.outputs.aws_access_key_id }} - AWS_SECRET_ACCESS_KEY: ${{ steps.aws-assume-role.outputs.aws_secret_key }} - AWS_SESSION_TOKEN: ${{ steps.aws-assume-role.outputs.aws_sessions_token }} run: | aws ecr get-login-password --region ${REGION} | docker login --username AWS --password-stdin ${ECR_REGISTRY_ID}.dkr.ecr.${REGION}.amazonaws.com - aws ecr --region $REGION describe-repositories --registry-id $ECR_REGISTRY_ID --repository-names ${GITHUB_REPOSITORY#*/} || aws ecr --region $REGION create-repository --registry-id $ECR_REGISTRY_ID --repository-name ${GITHUB_REPOSITORY#*/} - aws ecr --region $REGION set-repository-policy --registry-id $ECR_REGISTRY_ID --repository-name ${GITHUB_REPOSITORY#*/} --policy-text file:///home/runner/repo-access-permissions.json docker build -t ${ECR_REGISTRY_ID}.dkr.ecr.${REGION}.amazonaws.com/${GITHUB_REPOSITORY#*/}:${GITHUB_SHA} . docker push ${ECR_REGISTRY_ID}.dkr.ecr.${REGION}.amazonaws.com/${GITHUB_REPOSITORY#*/}:${GITHUB_SHA} + + docker build -t ${ECR_REGISTRY_ID}.dkr.ecr.${REGION}.amazonaws.com/faucet:${GITHUB_SHA} -f Dockerfile.alltools . + docker push ${ECR_REGISTRY_ID}.dkr.ecr.${REGION}.amazonaws.com/faucet:${GITHUB_SHA} # CD: # needs: [CI] # runs-on: [self-hosted,qa-infra-k8s] diff --git a/cmd/faucet/faucet.html b/cmd/faucet/faucet.html index 950f811f7..264129a49 100644 --- a/cmd/faucet/faucet.html +++ b/cmd/faucet/faucet.html @@ -5,6 +5,7 @@ + {{.Network}}: Faucet diff --git a/cmd/faucet/website.go b/cmd/faucet/website.go index 25e51051e..3bf97349c 100644 --- a/cmd/faucet/website.go +++ b/cmd/faucet/website.go @@ -1,13 +1,11 @@ -// Code generated by go-bindata. DO NOT EDIT. +// Code generated for package main by go-bindata DO NOT EDIT. (@generated) // sources: -// faucet.html (9.01kB) - +// faucet.html package main import ( "bytes" "compress/gzip" - "crypto/sha256" "fmt" "io" "io/ioutil" @@ -20,7 +18,7 @@ import ( func bindataRead(data []byte, name string) ([]byte, error) { gz, err := gzip.NewReader(bytes.NewBuffer(data)) if err != nil { - return nil, fmt.Errorf("read %q: %w", name, err) + return nil, fmt.Errorf("Read %q: %v", name, err) } var buf bytes.Buffer @@ -28,7 +26,7 @@ func bindataRead(data []byte, name string) ([]byte, error) { clErr := gz.Close() if err != nil { - return nil, fmt.Errorf("read %q: %w", name, err) + return nil, fmt.Errorf("Read %q: %v", name, err) } if clErr != nil { return nil, err @@ -38,9 +36,8 @@ func bindataRead(data []byte, name string) ([]byte, error) { } type asset struct { - bytes []byte - info os.FileInfo - digest [sha256.Size]byte + bytes []byte + info os.FileInfo } type bindataFileInfo struct { @@ -50,26 +47,37 @@ type bindataFileInfo struct { modTime time.Time } +// Name return file name func (fi bindataFileInfo) Name() string { return fi.name } + +// Size return file size func (fi bindataFileInfo) Size() int64 { return fi.size } + +// Mode return file mode func (fi bindataFileInfo) Mode() os.FileMode { return fi.mode } + +// Mode return file modify time func (fi bindataFileInfo) ModTime() time.Time { return fi.modTime } + +// IsDir return file whether a directory func (fi bindataFileInfo) IsDir() bool { - return false + return fi.mode&os.ModeDir != 0 } + +// Sys return file is sys mode func (fi bindataFileInfo) Sys() interface{} { return nil } -var _faucetHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xd4\x5a\xeb\x8f\xe3\xb6\x11\xff\xec\xfd\x2b\x26\xea\x25\x96\xbb\x2b\xc9\xbe\xcd\x0b\xb6\xe4\xe2\x72\x49\x83\x2b\xda\x4b\x90\x4b\xd0\x16\x49\x3e\xd0\xe2\xd8\xe2\x2e\x45\x2a\x24\x65\xaf\x63\xf8\x7f\x2f\x48\x51\xb2\xfc\xd8\xed\x3d\x02\x14\xbd\x0f\x5e\x91\x1c\xce\xfc\x38\x33\x9c\x87\x74\xe9\x47\x5f\x7f\xf7\xf2\xc7\x7f\x7f\xff\x0d\x14\xa6\xe4\xf3\xab\xd4\xfe\x01\x4e\xc4\x2a\x0b\x50\x04\x76\x02\x09\x9d\x5f\x0d\xd2\x12\x0d\x81\xbc\x20\x4a\xa3\xc9\x82\xda\x2c\xa3\x2f\x83\x6e\xbe\x30\xa6\x8a\xf0\xb7\x9a\xad\xb3\xe0\x5f\xd1\x4f\x2f\xa2\x97\xb2\xac\x88\x61\x0b\x8e\x01\xe4\x52\x18\x14\x26\x0b\x5e\x7d\x93\x21\x5d\xe1\x61\x9b\x20\x25\x66\xc1\x9a\xe1\xa6\x92\xca\xf4\x28\x37\x8c\x9a\x22\xa3\xb8\x66\x39\x46\x6e\x70\x03\x4c\x30\xc3\x08\x8f\x74\x4e\x38\x66\x93\x60\x7e\x75\x35\x48\x0d\x33\x1c\xe7\xbb\x5d\xfc\x1a\xcd\x46\xaa\xfb\xfd\x7e\x0a\x7f\x25\x75\x8e\x26\x4d\x9a\x35\x4b\xc5\x99\xb8\x87\x42\xe1\x32\x0b\x2c\x52\x3d\x4d\x92\x9c\x8a\x3b\x1d\xe7\x5c\xd6\x74\xc9\x89\xc2\x38\x97\x65\x42\xee\xc8\x43\xc2\xd9\x42\x27\x66\xc3\x8c\x41\x15\x2d\xa4\x34\xda\x28\x52\x25\xb7\xf1\x6d\xfc\x45\x92\x6b\x9d\x74\x73\x71\xc9\x44\x9c\x6b\x1d\x80\x42\x9e\x05\xda\x6c\x39\xea\x02\xd1\x04\x90\xcc\xdf\x4b\xec\x52\x0a\x13\x91\x0d\x6a\x59\x62\xf2\x69\xfc\x45\x3c\x76\x12\xfb\xd3\x4f\x0b\xbd\x1a\xa4\x3a\x57\xac\x32\xa0\x55\xfe\xd6\x62\xef\x7e\xab\x51\x6d\x93\xdb\x78\x12\x4f\xfc\xc0\x89\xb9\xd3\xc1\x3c\x4d\x1a\x86\xf3\x0f\x61\x1d\x09\x69\xb6\xc9\xf3\xf8\xd3\x78\x92\x54\x24\xbf\x27\x2b\xa4\xad\x20\xbb\x14\xb7\x93\x7f\x94\xd8\xc7\xec\x77\x77\x6a\xbe\x3f\x40\x56\x29\x4b\x14\x26\xbe\xd3\xc9\xf3\x78\xf2\x65\x3c\x6e\x27\xce\xd9\x5b\xfe\xd6\x5e\xf3\xab\xc1\x20\x5e\xa3\x32\x2c\x27\x3c\xca\x51\x18\x54\xb0\xbb\x1a\x0c\x06\x25\x13\x51\x81\x6c\x55\x98\x29\x4c\xc6\xe3\x8f\x67\x17\x26\xd7\x85\x9b\xa5\x4c\x57\x9c\x6c\xa7\xb0\xe4\xf8\xe0\x66\x08\x67\x2b\x11\x31\x83\xa5\x9e\x42\xc3\xd5\xce\xef\xad\xb4\x4a\xc9\x95\x42\xad\x1b\x31\x95\xd4\xcc\x30\x29\xa6\xd6\x89\x88\x61\x6b\x3c\x27\xd4\x15\x11\xa7\xd4\x64\xa1\x25\xaf\x0d\x1e\x03\x58\x70\x99\xdf\xbb\x29\x77\x55\x7b\xc8\x73\xc9\xa5\x9a\xc2\xa6\x60\xa6\x93\x50\x29\xf4\x6c\x09\xa5\x4c\xac\xa6\xf0\x79\xd5\xe0\x2f\x89\x5a\x31\x31\x85\xb1\x27\x4d\x13\xaf\xad\x34\x69\xa2\xd0\x55\xba\x90\x74\x3b\xbf\x4a\x29\x5b\x43\xce\x89\xd6\x59\x70\xa2\x46\x17\x5c\x7a\xcb\x36\xa4\x10\x26\x9a\x85\xa3\x15\x25\x37\x01\x38\x01\x59\xd0\x48\x8e\x16\xd2\x18\x59\x4e\x61\x62\x11\xb9\x0d\x27\xbc\x78\xc4\x57\xd1\xe4\x79\xb3\x34\x48\x8b\x49\xcb\xc0\xe0\x83\x89\x9c\xfe\x3b\xcd\x07\xf3\x94\xb5\x3b\x97\x04\x96\x24\x5a\x10\x53\x04\x40\x14\x23\x51\xc1\x28\x45\x91\x05\x46\xd5\x68\x3d\x84\xcd\xa1\x1f\xc4\xba\x18\x56\x4c\x1a\x14\x09\x65\x6b\x77\x80\xee\xe1\xe4\x24\x8f\x81\xfd\x12\xfc\x83\x5c\x2e\x35\x9a\xa8\xc3\xde\x23\x65\xa2\xaa\x4d\xb4\x52\xb2\xae\xfc\xea\x20\x75\x73\xc0\x68\x16\xd4\x8a\x07\x3e\x52\xbb\x47\xb3\xad\xfc\x81\x83\xee\x78\x52\x95\x91\xd5\xb4\x92\x3c\x80\x8a\x93\x1c\x0b\xc9\x29\xaa\x2c\x78\x23\x73\x46\x38\x88\xe6\x64\xf0\xd3\x0f\x7f\x07\x6f\x12\x26\x56\xb0\x95\xb5\x82\xaf\x5e\xbc\x01\x42\xa9\x75\xba\x38\x8e\x3b\x04\xce\xff\xce\x11\x46\x0b\x23\x5a\x1a\x4b\xb6\xa8\x8d\x91\x1d\xe1\xc2\x08\x58\x18\x11\x51\x5c\x92\x9a\x1b\xa0\x4a\x56\x54\x6e\x44\x64\xe4\x6a\x65\x93\x51\x83\xbe\xd9\x14\x00\x25\x86\xf8\xa5\x2c\x68\x69\x5b\x13\x11\x5d\xc9\xaa\xae\xbc\x91\x9a\x49\x7c\xa8\x88\xa0\x48\xad\x49\xb9\xc6\x60\xfe\x2d\x5b\x23\x94\x08\xaf\xdd\x2d\x82\x1f\xe5\x3d\x8a\xc1\xa9\xe1\x73\xa2\xd0\x44\x7d\xde\x67\xe6\x4f\x93\x06\x53\x73\x32\xf0\xff\xd2\x9a\xb7\x9c\xba\x93\x94\x28\x6a\x38\x1a\x45\xca\xc6\x86\x60\xbe\xdb\x29\x22\x56\x08\xcf\x18\x7d\xb8\x81\x67\xa4\x94\xb5\x30\x30\xcd\x20\x7e\xe1\x1e\xf5\x7e\x7f\xc4\x1d\x20\xe5\x6c\x9e\x92\xa7\x9c\x18\xa4\xc8\x39\xcb\xef\xb3\xc0\x30\x54\xd9\x6e\x67\x99\xef\xf7\x33\xbd\x2d\x17\x92\x67\xc3\xe6\xdc\xee\xd8\xc3\x19\xec\x76\x6c\x09\xcf\xe2\x1f\x30\x27\x95\xc9\x0b\xb2\xdf\xaf\x54\xfb\x1c\xe3\x03\xe6\xb5\xc1\x70\xb4\xdb\x21\xd7\xb8\xdf\xeb\x7a\x51\x32\x13\xb6\x3c\xed\xbc\xa0\xfb\xbd\x3d\x88\x07\xbf\xdf\xa7\x09\x99\xa7\x09\x67\x73\xbf\x78\xac\x9e\xa4\xe6\x9d\x2b\xa4\x89\xf5\x18\x3f\xdc\xed\x80\x2d\x21\xfe\x0a\xab\xe7\xf8\x4a\x2c\xa5\x06\xbf\xf5\xff\xc5\xaf\xbe\xc7\xd5\x6a\x0b\xc6\xea\x55\xff\x8f\xdc\x09\x3a\x7f\x6a\x8c\x7d\x03\xcf\x16\xad\x3e\x9d\x57\x1d\xb4\xdb\x2a\xd7\x2a\xee\x1d\x5c\xca\x3b\xd1\x6e\xe7\x25\xec\xf7\xef\xe7\x42\x0e\x48\xd8\x63\x73\xe4\x4a\x1d\x68\x7f\x0d\xde\x18\xb5\xdf\x43\x8f\xfa\xfd\x7d\x0c\x05\x6d\x1d\xab\x89\xcc\x0e\x7d\x1f\xfc\x59\xb0\x5d\x45\xdd\x71\xbc\x9f\x68\x66\xf0\x1e\xb7\x59\xb0\xdb\xf5\x77\xfa\xd5\x9c\x70\xbe\x20\x4e\x5b\xee\xac\xdd\xa6\xdf\xd1\xfa\xef\x9a\x69\x57\x65\xcf\x5b\xf9\xdd\x09\xfe\x7b\xce\x38\xc9\x7e\x46\x56\x53\xb8\x7d\xfe\x54\xea\xfb\xfc\x24\x9b\xdc\x5e\xc8\x26\x15\x11\xc8\xc1\xfd\x46\xba\x24\xbc\x7d\xf6\x57\xa7\x8b\xef\xa7\x5b\x22\x9b\xdb\x3b\x4c\x5d\x71\x30\x9e\x81\x5c\xa3\x5a\x72\xb9\x99\x02\xa9\x8d\x9c\x41\x49\x1e\xba\x7a\xe8\x76\x3c\xee\x00\x5b\xae\x86\x2c\x38\xba\xbc\xa5\xf0\xb7\x1a\xb5\xd1\x5d\x96\x6a\x96\xdc\xaf\x4d\x56\x14\x85\x46\x7a\xa2\x04\x2b\xcf\xea\xd2\x51\xb5\x48\x5b\xfd\x5d\x44\xbd\x94\xd2\x97\x1d\x7d\x00\x9e\x69\xaf\x1e\x0a\xe6\xa9\x51\x07\x47\x32\xf4\x9d\x4a\x07\x65\x0b\xfe\xc7\x2a\x87\x26\xa4\xd9\x33\x57\x88\xaa\xa9\x38\xad\x9b\x82\x1b\xa6\x89\xa1\xef\x2d\xd7\xfa\xda\x82\x68\x7c\x1b\xe1\xae\x0c\x3c\x08\x77\xc3\x0f\x93\x5e\x20\x51\x66\x81\xc4\xbc\x8d\xf8\x65\x2d\x68\xef\xec\xfd\x84\xfc\x61\x28\x6a\xc1\xd6\xa8\x34\x33\xdb\xb7\x85\x81\xf4\x80\xa3\x19\xf7\x01\xa4\x89\x51\x8f\xbb\xd8\xe1\xf1\xec\x02\xfb\xbf\xfe\xcf\x55\xda\x75\x2d\x49\x02\xdf\x72\xb9\x20\x1c\xd6\x16\xe0\x82\xa3\x06\x23\xc1\xd6\x60\x60\x0a\x84\xbc\x56\x0a\x85\x01\x6d\x88\xa9\x35\xc8\xa5\x9b\x5d\xba\x1a\xf3\x6a\xb0\x26\x0a\x88\x31\x58\x56\x06\x32\x57\x7c\xdb\x19\x8d\x6a\xed\xfa\x07\x3b\xb0\xb9\xbf\xbf\xd6\xc4\xed\x20\xf0\xe3\xf6\xaa\x41\x06\x3f\xff\x3a\xbb\x72\x80\xbe\xc6\x25\x13\x08\xc4\x2a\x20\xb7\xdd\x03\x98\x82\x18\xc8\x15\x12\x83\x1a\x72\x2e\x75\xad\x1a\x9c\x36\xfb\x80\xc5\xda\xf2\x69\xb8\xda\xe9\xca\xc9\x6d\x59\x84\x05\xd1\xc5\xc8\x75\x0f\x0a\x4d\xad\xc4\x61\xa5\x99\x1d\x2c\xa5\x82\xd0\x6e\x66\xd9\x78\x06\x2c\x6d\x39\xc6\x1c\xc5\xca\x14\x33\x60\xd7\xd7\x9e\x74\xc0\x96\x10\xb6\xeb\x3f\xb3\x5f\x63\xf3\x10\x5b\xfe\x90\x65\x70\x90\x33\xb0\xa2\x3c\x0f\x5d\x71\x96\x63\xc8\x6e\x60\x32\x9a\x35\x6b\x0b\x85\xa4\x69\x7d\x5c\x6f\xe3\x7e\xf6\x57\x83\xfd\xac\xaf\x03\xa7\xec\x23\x2d\x34\xa1\x5c\x03\x81\x15\xd3\x06\x6a\xc5\xad\x1e\x2c\x5d\xa3\x76\xaf\x66\x47\xd5\x3f\xff\x59\x7a\xf1\x0f\x3e\xec\x37\x90\x1b\x16\xb1\x46\x41\xc3\xbf\xbd\xf9\xee\x75\xac\x8d\x62\x62\xc5\x96\xdb\x70\x57\x2b\x3e\x85\x67\x61\xf0\x27\x5b\xca\x8f\x7e\x1e\xff\x1a\xaf\x09\xaf\xf1\xc6\x9b\x74\x0a\x6d\xaa\xb7\x16\x9f\xba\xdf\x33\x99\x37\xe0\x1f\xa7\x70\x2c\x7e\x3f\x1a\xcd\x2e\x25\xc0\x5e\x02\x57\xa8\xd1\x84\x96\xcc\xe7\xa9\x63\x4d\x11\x28\xd1\x14\x92\x5a\x6d\x28\xcc\xa5\x10\x98\x1b\xa8\x2b\x29\xbc\x62\x80\x4b\xad\x5b\xa7\x6b\xd7\xb3\x53\x37\xf0\xb4\x19\x08\xdc\xc0\x3f\x71\xf1\x46\xe6\xf7\x68\xc2\x30\xdc\x30\x41\xe5\x26\xe6\x32\x27\x96\xdc\x36\xbb\x46\xe6\x92\x43\x96\x65\xe0\xfb\xfd\x60\x04\x7f\x81\x60\xa3\x6d\xe7\x1f\xc0\xd4\x3e\xda\xa7\x11\x5c\xc3\xe9\xf6\x42\x6a\x03\xd7\x10\x24\xcd\x55\xb2\xe9\x4e\x99\x84\x54\x2c\x18\xd9\x5b\xd0\x5a\x42\x8a\x12\xb5\x26\x2b\xec\x23\xc5\x35\x0a\xe3\x7d\xcc\x1e\xa7\xd4\x2b\xc8\xc0\xd9\xab\x22\x4a\x63\x43\x10\xdb\x00\xdc\x38\x9b\x75\x57\x47\x94\x65\x20\x6a\xce\x5b\xff\x6c\x6e\xc2\xac\xf1\xbe\x1e\x61\xec\x02\x22\x7c\x94\x65\x60\x43\x90\xd5\x2f\x6d\xf7\x58\x0f\x68\xe2\xe5\x28\xb6\x31\xf0\x40\x3f\x9a\xb5\x6e\x7c\xc4\x07\xe9\xd3\x8c\x90\x9e\x72\x42\x7a\x81\x95\x4b\x48\x8f\x73\x6a\xd2\x57\x8f\x91\x9b\xb8\xc0\x47\xd4\xe5\x02\xd5\xe3\x8c\x9a\x54\xe4\x19\x39\x75\xbe\x12\xa6\xb7\xf3\x06\x26\x9f\x8f\x2e\xf0\x45\xa5\xe4\x23\x6c\x85\x34\xdb\x70\xc7\xc9\x56\xd6\x66\x0a\x43\x23\xab\x97\x2e\x61\x0c\x6f\xc0\x4a\x99\x42\xb7\xff\xc6\x35\x03\x53\x18\xba\x91\x5d\x67\x25\xba\x5d\x9f\x8d\xc7\xe3\x1b\x68\xdf\xb0\x7c\x45\xec\x0d\x53\x35\xee\x2f\x20\xd1\x75\x9e\xa3\x7e\x44\x57\x6f\x85\xc5\x73\xe8\xd0\xf8\xf1\x7b\xe2\xe9\x42\xfc\x11\x20\xf8\xe4\x13\x38\x5b\xed\x3b\x67\x92\xc0\x3f\x88\xba\x07\x57\x06\x2a\x5c\x33\x59\xeb\x43\xba\x28\x99\xd6\x4c\xac\x80\x68\xa0\x52\xa0\xdb\xf1\x2e\x11\xfc\x0c\x9d\x27\x82\x39\x8c\x4f\xa1\xd9\x58\xd7\x8b\xf0\x17\x02\x7f\xc7\xb5\x1f\xd5\x07\xfb\x83\xa4\xa3\x3d\xac\x44\xf8\x28\x83\x20\x38\x6c\x3b\x5b\xb7\xcb\x9e\xcd\x40\xa3\xf9\xb1\xd1\x7b\xe8\x13\xdb\xa5\xe4\x33\xba\xb1\x15\xed\x78\x74\x24\x7c\xdf\xaa\xf2\x45\x55\xd9\x8e\x83\x88\xad\x8b\x6c\x9d\x1e\x99\x30\x12\x64\x6d\xa3\x63\x4e\xb8\xad\xd1\x39\xba\x28\xe3\x36\x5a\x65\xe6\xb2\x2c\xa5\x80\x0c\xa2\xc9\xec\x2c\xf9\xf5\xb4\xd6\x1d\xe6\xd4\x0c\x17\xb4\x7c\x6c\x8a\x63\x0d\x9d\x90\x46\x93\x23\xe5\x1f\xd9\xe5\x92\x01\x06\x1d\x5e\xd6\xea\xef\xc8\x28\xad\x55\xfa\xfa\xe9\x21\x6e\x76\x5f\x4f\xde\x0a\x78\xb7\x58\xd5\xba\x08\x4f\xa0\x8d\x66\xc7\x16\x78\x65\x50\x11\x83\xae\x25\x71\x1a\x47\x61\x98\xc2\x33\xc5\x03\x11\xb6\x9c\x89\x14\x0a\x8a\xaa\xad\x00\x6c\x47\xd3\x34\x20\x3d\xc3\xb8\x4f\x1e\x3d\x57\xe9\x9d\xe3\x4c\x8b\x33\x60\x30\xb7\x75\x18\xb0\x28\xea\x4e\xe0\x8a\x25\x29\xd0\xb6\xab\x27\x9e\xed\xbc\xb0\xe7\x86\x96\x14\x39\xa9\x34\x52\xc8\xa0\x79\x51\x1d\x8e\xe2\x5a\xb0\x87\x70\x14\xf9\xf1\x29\x87\x76\xdd\xe5\x34\x67\x9c\x06\xf3\x75\x06\x41\x6a\x94\x2d\x7b\x87\x01\x5c\x5f\xba\x53\x36\x3b\x0e\xe7\xad\xf4\xfe\x46\x80\xd4\xd0\xb9\xeb\xa7\x9a\x62\xfc\x97\xc0\xb6\xb9\x2b\x25\x6b\x41\xa7\xb6\x24\x0a\xcf\x98\x92\x35\x31\x44\x39\x9e\xa3\x19\x1c\xc8\x5d\x37\x3c\x85\xdc\x5a\x65\x06\x4d\xd3\xe5\x1a\x59\xe8\xda\x44\x37\x5a\x48\x45\x51\x45\x8a\x50\x56\xeb\x29\x7c\x5a\x3d\xcc\x7e\x69\x3b\x67\x57\xa1\x3f\x01\xb4\x52\x38\x3f\xc3\x93\xe7\xee\x15\xdb\x35\x04\x69\x62\x09\x9e\x66\xd2\x1d\xb4\xff\x9a\x1c\x2e\xf4\x20\xd0\xbd\xd4\xf6\xf3\x25\xa3\x94\xa3\x05\xdb\x32\xb7\xb7\xcd\xda\xfc\x70\x67\x8e\xc5\x81\x6f\x3c\x5a\xfa\x3d\x20\xd7\xf8\x28\x71\xd7\xbf\x0c\xad\xc1\x23\x7b\x50\xe6\xf4\xec\x5b\x21\x37\xad\x86\x4e\x03\xfe\xf3\x06\xad\x95\xab\x82\xc2\xc8\x3b\xd4\x0d\x0c\xb5\xad\xc9\xa8\x1e\x8e\xe2\xa2\x2e\x89\x60\xbf\x63\x68\x13\xca\xa8\xd1\x90\x6b\x88\x82\xe3\xb8\x7a\x06\xe4\xd0\x60\x0f\xdb\xc4\x34\xf4\x8a\x1b\xb6\xd6\xb4\x86\x83\x43\xc3\x3e\x7c\x07\xad\x5c\x96\x10\x2d\x88\x82\xfe\x20\x6a\xb3\x25\x28\x69\x25\xb7\x6b\x0b\xa2\x86\x4d\x13\xe8\xea\x66\x21\x37\xd9\xf0\x76\xdc\x01\x6c\x0c\xeb\xec\x3a\xf4\x7e\x75\x62\x00\x8b\xb0\xbd\x80\x73\xb8\x1d\x7f\x38\x52\x4a\xc4\x0a\x4f\xd1\x1b\xc5\x2a\xa4\x40\x72\xdb\x04\xff\xe1\x87\xf8\x60\xe5\xbe\x33\x3c\xeb\x77\xad\xda\x9c\x5b\x1e\x61\xb5\xab\x9d\x56\xff\x6c\xef\x15\x24\x4e\xb7\xd7\x10\x5c\x38\xc4\x23\x9e\x77\x44\x74\x72\x79\x1f\xbb\xd7\xae\x97\x0f\xfa\x49\xc2\x96\x9f\xdd\xab\xa7\x51\x5c\x98\x92\x87\x41\x6a\xdc\x87\x2b\x8b\xb3\xdb\xed\x36\x37\xd3\x87\x7a\x6b\xdf\xef\x1a\x6c\x8f\x8c\x27\xdd\x0d\xf4\xea\x88\xae\x03\x6a\x8b\x06\xb0\xdd\xd4\xde\x35\x54\x6f\x0c\x51\x06\x08\xfc\xf4\x0a\xea\x8a\x12\x63\x93\x90\x04\x9b\xe2\x5c\x32\xea\xbe\xf2\x2d\x88\xd2\xb0\x94\x6a\x43\x14\x85\x5a\x18\xc6\xed\xfa\x16\x88\x42\x5f\x93\x69\x34\xaf\x6c\x54\x5a\x13\x1e\x9e\xf4\x59\xcf\xc2\x61\xdc\x37\xec\x70\x14\x23\xc9\x8b\x53\x32\x97\x75\x3a\x89\x19\xbc\x76\x35\x78\xf8\x2c\x34\x05\xd3\xa3\x98\x18\xa3\xc2\xe1\x91\xc1\x87\x23\x6b\xbb\x49\xd7\xf7\x74\x9b\xd3\xde\x95\x79\x6a\xff\xa1\xaa\xf5\x19\xbc\x25\xce\xb5\x0e\x1b\xaf\x19\xde\xf4\xf8\x1e\x3b\xcd\xf0\xe3\xa1\x37\xc9\xe1\xd2\x1e\xf0\x67\x17\x30\x1c\xb1\x1d\xda\xbb\x33\x3c\x11\x4c\x28\x7d\x69\xef\x45\x18\x5c\xb8\xbd\x7d\x0f\x18\x79\xc5\x36\x11\xf7\x09\x8d\x32\x41\xf1\xe1\x31\x75\x32\x3a\x1c\xc5\xba\x5e\x34\xbd\x7f\xf8\x99\xef\x76\x5a\x22\xe7\x96\xa7\x81\xfc\x2c\xfd\x5b\x01\xc7\x25\x40\x74\x52\x32\x3c\x11\xf3\x9d\x40\x7b\x9a\xfd\x8d\x55\xee\x78\xe4\x5f\x0c\x7d\xa3\x6d\x05\xc4\x74\x01\x04\x36\xb8\xd0\xae\x37\x07\xef\xc9\xee\x0d\x49\xf3\x26\xe4\xc5\xf7\xaf\xba\xb7\x21\x9d\xa7\xdb\x22\xa4\xfb\x9e\x7e\xfe\xae\xe1\xe2\xe7\xfb\xcd\x66\x13\xaf\xa4\x5c\xf1\xe6\xc3\x7d\xf7\x32\xc2\x36\xea\xf1\x9d\x0e\x80\xe8\xad\xc8\x81\xe2\x12\xd5\xbc\xc7\xbc\x79\x43\x91\x26\xfe\x9b\x73\xd2\xfc\x0f\x99\xff\x04\x00\x00\xff\xff\x13\xef\x26\xa6\x32\x23\x00\x00") +var _faucetHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xd4\x5a\xeb\x8f\xe3\xb6\x11\xff\xec\xfd\x2b\x26\xea\x25\x96\xbb\x2b\xc9\xbe\xcd\x0b\xb6\xe4\xe2\x72\x49\x83\x2b\xda\x4b\x90\x4b\xd0\x16\x49\x3e\xd0\xe2\xd8\xe2\x2e\x45\x2a\x24\x65\xaf\x63\xf8\x7f\x2f\x48\x51\xb2\xfc\xd8\xed\x3d\x02\x14\xbd\x0f\x5e\x91\x1c\xce\xfc\x38\x33\x9c\x87\x74\xe9\x47\x5f\x7f\xf7\xf2\xc7\x7f\x7f\xff\x0d\x14\xa6\xe4\xf3\xab\xd4\xfe\x01\x4e\xc4\x2a\x0b\x50\x04\x76\x02\x09\x9d\x5f\x0d\xd2\x12\x0d\x81\xbc\x20\x4a\xa3\xc9\x82\xda\x2c\xa3\x2f\x83\x6e\xbe\x30\xa6\x8a\xf0\xb7\x9a\xad\xb3\xe0\x5f\xd1\x4f\x2f\xa2\x97\xb2\xac\x88\x61\x0b\x8e\x01\xe4\x52\x18\x14\x26\x0b\x5e\x7d\x93\x21\x5d\xe1\x61\x9b\x20\x25\x66\xc1\x9a\xe1\xa6\x92\xca\xf4\x28\x37\x8c\x9a\x22\xa3\xb8\x66\x39\x46\x6e\x70\x03\x4c\x30\xc3\x08\x8f\x74\x4e\x38\x66\x93\x60\x7e\x75\x35\x48\x39\x13\xf7\xa0\x90\x67\x01\xcb\xa5\x08\xa0\x50\xb8\xcc\x02\x0b\x47\x4f\x93\x64\x29\xf2\xad\xce\x89\x88\xed\x43\xbc\x91\x8a\xd3\x64\x49\xd6\x96\x34\x66\xb9\x74\x40\x0c\x33\x1c\xe7\xbb\x5d\xfc\x1a\xcd\x46\xaa\xfb\xfd\x7e\x0a\x7f\x25\x75\x8e\x26\x4d\x9a\xb5\x4e\xce\x31\xf3\x9c\x8a\x3b\x1d\xe7\x5c\xd6\x74\xc9\x89\xc2\x38\x97\x65\x42\xee\xc8\x43\xc2\xd9\x42\x27\x66\xc3\x8c\x41\x15\x2d\xa4\x34\xda\x28\x52\x25\xb7\xf1\x6d\xfc\x45\x92\x6b\x9d\x74\x73\x71\xc9\x44\x9c\x6b\x1d\x34\x67\xd0\x66\xcb\x51\x17\x88\x26\x80\x64\xfe\x5e\x62\x97\x52\x98\x88\x6c\x50\xcb\x12\x93\x4f\xe3\x2f\xe2\xb1\x93\xd8\x9f\x7e\x5a\xe8\xd5\x20\xd5\xb9\x62\x95\x01\xad\xf2\xb7\x16\x7b\xf7\x5b\x8d\x6a\x9b\xdc\xc6\x93\x78\xe2\x07\x4e\xcc\x9d\x0e\xe6\x69\xd2\x30\x9c\x7f\x08\xeb\x48\x48\xb3\x4d\x9e\xc7\x9f\xc6\x93\xa4\x22\xf9\x3d\x59\x21\x6d\x05\xd9\xa5\xb8\x9d\xfc\xa3\xc4\x3e\x66\xbf\xbb\x53\xf3\xfd\x01\xb2\x4a\x59\xa2\x30\xf1\x9d\x4e\x9e\xc7\x93\x2f\xe3\x71\x3b\x71\xce\xde\xf2\xb7\xf6\x9a\x5f\x0d\x06\xf1\x1a\x95\x61\x39\xe1\x51\x8e\xc2\xa0\x82\xdd\xd5\x60\x30\x28\x99\x88\x0a\x64\xab\xc2\x4c\x61\x32\x1e\x7f\x3c\xbb\x30\xb9\x2e\xdc\x2c\x65\xba\xe2\x64\x3b\x85\x25\xc7\x07\x37\x43\x38\x5b\x89\x88\x19\x2c\xf5\x14\x1a\xae\x76\x7e\x6f\xa5\x55\x4a\xae\x14\x6a\xdd\x88\xa9\xa4\x66\x86\x49\x31\xb5\x4e\x44\x0c\x5b\xe3\x39\xa1\xae\x88\x38\xa5\x26\x0b\x2d\x79\x6d\xf0\x18\xc0\x82\xcb\xfc\xde\x4d\xb9\xcb\xde\x43\x9e\x4b\x2e\xd5\x14\x36\x05\x33\x9d\x84\x4a\xa1\x67\x4b\x28\x65\x62\x35\x85\xcf\xab\x06\x7f\x49\xd4\x8a\x89\x29\x8c\x3d\x69\x9a\x78\x6d\xa5\x49\x13\xc7\xae\xd2\x85\xa4\xdb\xf9\x55\x4a\xd9\x1a\x72\x4e\xb4\xce\x82\x13\x35\xba\xa8\xd0\x5b\xb6\x41\x89\x30\xd1\x2c\x1c\xad\x28\xb9\x09\xc0\x09\xc8\x82\x46\x72\xb4\x90\xc6\xc8\x72\x0a\x13\x8b\xc8\x6d\x38\xe1\xc5\x23\xbe\x8a\x26\xcf\x9b\xa5\x41\x5a\x4c\x5a\x06\x06\x1f\x4c\xe4\xf4\xdf\x69\x3e\x98\xa7\xac\xdd\xb9\x24\xb0\x24\xd1\x82\x98\x22\x00\xa2\x18\x89\x0a\x46\x29\x8a\x2c\x30\xaa\x46\xeb\x21\x6c\x0e\xfd\x20\xd6\xc5\xb0\x62\xd2\xa0\x48\x28\x5b\xbb\x03\x74\x0f\x27\x27\x79\x0c\xec\x97\xe0\x1f\xe4\x72\xa9\xd1\x44\x1d\xf6\x1e\x29\x13\x55\x6d\xa2\x95\x92\x75\xe5\x57\x07\xa9\x9b\x03\x46\xb3\xa0\x56\x3c\xf0\xb1\xde\x3d\x9a\x6d\xe5\x0f\x1c\x74\xc7\x93\xaa\x8c\xac\xa6\x95\xe4\x01\x54\x9c\xe4\x58\x48\x4e\x51\x65\xc1\x1b\x99\x33\xc2\x41\x34\x27\x83\x9f\x7e\xf8\x3b\x78\x93\x30\xb1\x82\xad\xac\x15\x7c\xf5\xe2\x0d\x10\x4a\xad\xd3\xc5\x71\xdc\x21\x70\xfe\x77\x8e\x30\x5a\x18\xd1\xd2\x58\xb2\x45\x6d\x8c\xec\x08\x17\x46\xc0\xc2\x88\x88\xe2\x92\xd4\xdc\x00\x55\xb2\xa2\x72\x23\x22\x23\x57\x2b\x9b\xce\x1a\xf4\xcd\xa6\x00\x28\x31\xc4\x2f\x65\x41\x4b\xdb\x9a\x88\xe8\x4a\x56\x75\xe5\x8d\xd4\x4c\xe2\x43\x45\x04\x45\x6a\x4d\xca\x35\x06\xf3\x6f\xd9\x1a\xa1\x44\x78\xed\x6e\x11\xfc\x28\xef\x51\x0c\x4e\x0d\x9f\x13\x85\x26\xea\xf3\x3e\x33\x7f\x9a\x34\x98\x9a\x93\x81\xff\x97\xd6\xbc\xe5\xd4\x9d\xa4\x44\x51\xc3\xd1\x28\x52\x36\x36\x04\xf3\xdd\x4e\x11\xb1\x42\x78\xc6\xe8\xc3\x0d\x3c\x23\xa5\xac\x85\x81\x69\x06\xf1\x0b\xf7\xa8\xf7\xfb\x23\xee\x00\x29\x67\xf3\x94\x3c\xe5\xc4\x20\x45\xce\x59\x7e\x9f\x05\x86\xa1\xca\x76\x3b\xcb\x7c\xbf\x9f\xe9\x6d\xb9\x90\x3c\x1b\x36\xe7\x76\xc7\x1e\xce\x60\xb7\x63\x4b\x78\x16\xff\x80\x39\xa9\x4c\x5e\x90\xfd\x7e\xa5\xda\xe7\x18\x1f\x30\xaf\x0d\x86\xa3\xdd\x0e\xb9\xc6\xfd\x5e\xd7\x8b\x92\x99\xb0\xe5\x69\xe7\x05\xdd\xef\xed\x41\x3c\xf8\xfd\x3e\x4d\xc8\x3c\x4d\x38\x9b\xfb\xc5\x63\xf5\x24\x35\xef\x5c\x21\x4d\xac\xc7\xf8\xe1\x6e\x07\x6c\x09\xf1\x57\x58\x3d\xc7\x57\x62\x29\x35\xf8\xad\xff\x2f\x7e\xf5\x3d\xae\x56\x5b\x30\x56\xaf\xfa\x7f\xe4\x4e\xd0\xf9\x53\x63\xec\x1b\x78\xb6\x68\xf5\xe9\xbc\xea\xa0\xdd\x56\xb9\x56\x71\xef\xe0\x52\xde\x89\x76\x3b\x2f\x61\xbf\x7f\x3f\x17\x72\x40\xc2\x1e\x9b\x23\x57\xea\x40\xfb\x6b\xf0\xc6\xa8\xfd\x1e\x7a\xd4\xef\xef\x63\x28\x68\xeb\x58\x4d\x64\x76\xe8\xfb\xe0\xcf\x82\xed\x2a\xea\x8e\xe3\xfd\x44\x33\x83\xf7\xb8\xcd\x82\xdd\xae\xbf\xd3\xaf\xe6\x84\xf3\x05\x71\xda\x72\x67\xed\x36\xfd\x8e\xd6\x7f\xd7\x4c\xbb\x3a\x7d\xde\xca\xef\x4e\xf0\xdf\x73\xc6\x49\xf6\x33\xb2\x9a\xc2\xed\xf3\xa7\x52\xdf\xe7\x27\xd9\xe4\xf6\x42\x36\xa9\x88\x40\x0e\xee\x37\xd2\x25\xe1\xed\xb3\xbf\x3a\x5d\x7c\x3f\xdd\x12\xd9\xdc\xde\x61\xea\x8a\x83\xf1\x0c\xe4\x1a\xd5\x92\xcb\xcd\x14\x48\x6d\xe4\x0c\x4a\xf2\xd0\xd5\x43\xb7\xe3\x71\x07\xd8\x72\x35\x64\xc1\xd1\xe5\x2d\x85\xbf\xd5\xa8\x8d\xee\xb2\x54\xb3\xe4\x7e\x6d\xb2\xa2\x28\x34\xd2\x13\x25\x58\x79\x56\x97\x8e\xaa\x45\xda\xea\xef\x22\xea\xa5\x94\xbe\xec\xe8\x03\xf0\x4c\x7b\xf5\x50\x30\x4f\x8d\x3a\x38\x92\xa1\xef\x54\x3a\x28\x5b\xf0\x3f\x56\x39\x34\x21\xcd\x9e\xb9\x42\x54\x4d\xc5\x69\xdd\x14\xdc\x30\x4d\x0c\x7d\x6f\xb9\xd6\xd7\x16\x44\xe3\xdb\x08\x77\x65\xe0\x41\xb8\x1b\x7e\x98\xf4\x02\x89\x32\x0b\x24\xe6\x6d\xc4\x2f\x6b\x41\x7b\x67\xef\x27\xe4\x0f\x43\x51\x0b\xb6\x46\xa5\x99\xd9\xbe\x2d\x0c\xa4\x07\x1c\xcd\xb8\x0f\x20\x4d\x8c\x7a\xdc\xc5\x0e\x8f\x67\x17\xd8\xff\xf5\x7f\xae\xd2\xae\x6b\x49\x12\xf8\x96\xcb\x05\xe1\xb0\xb6\x00\x17\x1c\x35\x18\x09\xb6\x06\x03\x53\x20\xe4\xb5\x52\x28\x0c\x68\x43\x4c\xad\x41\x2e\xdd\xec\xd2\xd5\x98\x57\x83\x35\x51\x40\x8c\xc1\xb2\x32\x90\xb9\xe2\xdb\xce\x68\x54\x6b\xd7\x3f\xd8\x81\xcd\xfd\xfd\xb5\x26\x6e\x07\x81\x1f\xb7\x57\x0d\x32\xf8\xf9\xd7\xd9\x95\x03\xf4\x35\x2e\x99\x40\x20\x56\x01\xb9\xed\x1e\xc0\x14\xc4\x40\xae\x90\x18\xd4\x90\x73\xa9\x6b\xd5\xe0\xb4\xd9\x07\x2c\xd6\x96\x4f\xc3\xd5\x4e\x57\x4e\x6e\xcb\x22\x2c\x88\x2e\x46\xae\x7b\x50\x68\x6a\x25\x0e\x2b\xcd\xec\x60\x29\x15\x84\x76\x33\xcb\xc6\x33\x60\x69\xcb\x31\xe6\x28\x56\xa6\x98\x01\xbb\xbe\xf6\xa4\x03\xb6\x84\xb0\x5d\xff\x99\xfd\x1a\x9b\x87\xd8\xf2\x87\x2c\x83\x83\x9c\x81\x15\xe5\x79\xe8\x8a\xb3\x1c\x43\x76\x03\x93\xd1\xac\x59\x5b\x28\x24\x4d\xeb\xe3\x7a\x1b\xf7\xb3\xbf\x1a\xec\x67\x7d\x1d\x38\x65\x1f\x69\xa1\x09\xe5\x1a\x08\xac\x98\x36\x50\x2b\x6e\xf5\x60\xe9\x1a\xb5\x7b\x35\x3b\xaa\xfe\xf9\xcf\xd2\x8b\x7f\xf0\x61\xbf\x81\xdc\xb0\x88\x35\x0a\x1a\xfe\xed\xcd\x77\xaf\x63\x6d\x14\x13\x2b\xb6\xdc\x86\xbb\x5a\xf1\x29\x3c\x0b\x83\x3f\xd9\x52\x7e\xf4\xf3\xf8\xd7\x78\x4d\x78\x8d\x37\xde\xa4\x53\x68\x53\xbd\xb5\xf8\xd4\xfd\x9e\xc9\xbc\x01\xff\x38\x85\x63\xf1\xfb\xd1\x68\x76\x29\x01\xf6\x12\xb8\x42\x8d\x26\xb4\x64\x3e\x4f\x1d\x6b\x8a\x40\x89\xa6\x90\xd4\x6a\x43\x61\x2e\x85\xc0\xdc\x40\x5d\x49\xe1\x15\x03\x5c\x6a\xdd\x3a\x5d\xbb\x9e\x9d\xba\x81\xa7\xcd\x40\xe0\x06\xfe\x89\x8b\x37\x32\xbf\x47\x13\x86\xe1\x86\x09\x2a\x37\x31\x97\x39\xb1\xe4\xb6\xd9\x35\x32\x97\x1c\xb2\x2c\x03\xdf\xef\x07\x23\xf8\x0b\x04\x1b\x6d\x3b\xff\x00\xa6\xf6\xd1\x3e\x8d\xe0\x1a\x4e\xb7\x17\x52\x1b\xb8\x86\x20\x69\xae\x92\x4d\x77\xca\x24\xa4\x62\xc1\xc8\xde\x82\xd6\x12\x52\x94\xa8\x35\x59\x61\x1f\x29\xae\x51\x18\xef\x63\xf6\x38\xa5\x5e\x41\x06\xce\x5e\x15\x51\x1a\x1b\x82\xd8\x06\xe0\xc6\xd9\xac\xbb\x3a\xa2\x2c\x03\x51\x73\xde\xfa\x67\x73\x13\x66\x8d\xf7\xf5\x08\x63\x17\x10\xe1\xa3\x2c\x03\x1b\x82\xac\x7e\x69\xbb\xc7\x7a\x40\x13\x2f\x47\xb1\x8d\x81\x07\xfa\xd1\xac\x75\xe3\x23\x3e\x48\x9f\x66\x84\xf4\x94\x13\xd2\x0b\xac\x5c\x42\x7a\x9c\x53\x93\xbe\x7a\x8c\xdc\xc4\x05\x3e\xa2\x2e\x17\xa8\x1e\x67\xd4\xa4\x22\xcf\xc8\xa9\xf3\x95\x30\xbd\x9d\x37\x30\xf9\x7c\x74\x81\x2f\x2a\x25\x1f\x61\x2b\xa4\xd9\x86\x3b\x4e\xb6\xb2\x36\x53\x18\x1a\x59\xbd\x74\x09\x63\x78\x03\x56\xca\x14\xba\xfd\x37\xae\x19\x98\xc2\xd0\x8d\xec\x3a\x2b\xd1\xed\xfa\x6c\x3c\x1e\xdf\x40\xfb\x86\xe5\x2b\x62\x6f\x98\xaa\x71\x7f\x01\x89\xae\xf3\x1c\xf5\x23\xba\x7a\x2b\x2c\x9e\x43\x87\xc6\x8f\xdf\x13\x4f\x17\xe2\x8f\x00\xc1\x27\x9f\xc0\xd9\x6a\xdf\x39\x93\x04\xfe\x41\xd4\x3d\xb8\x32\x50\xe1\x9a\xc9\x5a\x1f\xd2\x45\xc9\xb4\x66\x62\x05\x44\x03\x95\x02\xdd\x8e\x77\x89\xe0\x67\xe8\x3c\x11\xcc\x61\x7c\x0a\xcd\xc6\xba\x5e\x84\xbf\x10\xf8\x3b\xae\xfd\xa8\x3e\xd8\x1f\x24\x1d\xed\x61\x25\xc2\x47\x19\x04\xc1\x61\xdb\xd9\xba\x5d\xf6\x6c\x06\x1a\xcd\x8f\x8d\xde\x43\x9f\xd8\x2e\x25\x9f\xd1\x8d\xad\x68\xc7\xa3\x23\xe1\xfb\x56\x95\x2f\xaa\xca\x76\x1c\x44\x6c\x5d\x64\xeb\xf4\xc8\x84\x91\x20\x6b\x1b\x1d\x73\xc2\x6d\x8d\xce\xd1\x45\x19\xb7\xd1\x2a\x33\x97\x65\x29\x05\x64\x10\x4d\x66\x67\xc9\xaf\xa7\xb5\xee\x30\xa7\x66\xb8\xa0\xe5\x63\x53\x1c\x6b\xe8\x84\x34\x9a\x1c\x29\xff\xc8\x2e\x97\x0c\x30\xe8\xf0\xb2\x56\x7f\x47\x46\x69\xad\xd2\xd7\x4f\x0f\x71\xb3\xfb\x7a\xf2\x56\xc0\xbb\xc5\xaa\xd6\x45\x78\x02\x6d\x34\x3b\xb6\xc0\x2b\x83\x8a\x18\x74\x2d\x89\xd3\x38\x0a\xc3\x14\x9e\x29\x1e\x88\xb0\xe5\x4c\xa4\x50\x50\x54\x6d\x05\x60\x3b\x9a\xa6\x01\xe9\x19\xc6\x7d\x34\xe9\xb9\x4a\xef\x1c\x67\x5a\x9c\x01\x83\xb9\xad\xc3\x80\x45\x51\x77\x02\x57\x2c\x49\x81\xb6\x5d\x3d\xf1\x6c\xe7\x85\x3d\x37\xb4\xa4\xc8\x49\xa5\x91\x42\x06\xcd\x8b\xea\x70\x14\xd7\x82\x3d\x84\xa3\xc8\x8f\x4f\x39\xb4\xeb\x2e\xa7\x39\xe3\x34\x98\xaf\x33\x08\x52\xa3\x6c\xd9\x3b\x0c\xe0\xfa\xd2\x9d\xb2\xd9\x71\x38\x6f\xa5\xf7\x37\x02\xa4\x86\xce\x5d\x3f\xd5\x14\xe3\xbf\x04\xb6\xcd\x5d\x29\x59\x0b\x3a\xb5\x25\x51\x78\xc6\x94\xac\x89\x21\xca\xf1\x1c\xcd\xe0\x40\xee\xba\xe1\x29\xe4\xd6\x2a\x33\x68\x9a\x2e\xd7\xc8\x42\xd7\x26\xba\xd1\x42\x2a\x8a\x2a\x52\x84\xb2\x5a\x4f\xe1\xd3\xea\x61\xf6\x4b\xdb\x39\xbb\x0a\xfd\x09\xa0\x95\xc2\xf9\x19\x9e\x3c\x77\xaf\xd8\xae\x21\x48\x13\x4b\xf0\x34\x93\xee\xa0\xfd\xd7\xe4\x70\xa1\x07\x81\xee\xa5\xb6\x9f\x2f\x19\xa5\x1c\x2d\xd8\x96\xb9\xbd\x6d\xd6\xe6\x87\x3b\x73\x2c\x0e\x7c\xe3\xd1\xd2\xef\x01\xb9\xc6\x47\x89\xbb\xfe\x65\x68\x0d\x1e\xd9\x83\x32\xa7\x67\xdf\x0a\xb9\x69\x35\x74\x1a\xf0\x9f\x37\x68\xad\x5c\x15\x14\x46\xde\xa1\x6e\x60\xa8\x6d\x4d\x46\xf5\x70\x14\x17\x75\x49\x04\xfb\x1d\x43\x9b\x50\x46\x8d\x86\x5c\x43\x14\x1c\xc7\xd5\x33\x20\x87\x06\x7b\xd8\x26\xa6\xa1\x57\xdc\xb0\xb5\xa6\x35\x1c\x1c\x1a\xf6\xe1\x3b\x68\xe5\xb2\x84\x68\x41\x14\xf4\x07\x51\x9b\x2d\x41\x49\x2b\xb9\x5d\x5b\x10\x35\x6c\x9a\x40\x57\x37\x0b\xb9\xc9\x86\xb7\xe3\x0e\x60\x63\x58\x67\xd7\xa1\xf7\xab\x13\x03\x58\x84\xed\x05\x9c\xc3\xed\xf8\xc3\x91\x52\x22\x56\x78\x8a\xde\x28\x56\x21\x05\x92\xdb\x26\xf8\x0f\x3f\xc4\x07\x2b\xf7\x9d\xe1\x59\xbf\x6b\xd5\xe6\xdc\xf2\x08\xab\x5d\xed\xb4\xfa\x67\x7b\xaf\x20\x71\xba\xbd\x86\xe0\xc2\x21\x1e\xf1\xbc\x23\xa2\x93\xcb\xfb\xd8\xbd\x76\xbd\x7c\xd0\x4f\x12\xb6\xfc\xec\x5e\x3d\x8d\xe2\xc2\x94\x3c\x0c\x52\xe3\x3e\x5c\x59\x9c\xdd\x6e\xb7\xb9\x99\x3e\xd4\x5b\xfb\x7e\xd7\x60\x7b\x64\x3c\xe9\x6e\xa0\x57\x47\x74\x1d\x50\x5b\x34\x80\xed\xa6\xf6\xae\xa1\x7a\x63\x88\x32\x40\xe0\xa7\x57\x50\x57\x94\x18\x9b\x84\x24\xd8\x14\xe7\x92\x51\xf7\x95\x6f\x41\x94\x86\xa5\x54\x1b\xa2\x28\xd4\xc2\x30\x6e\xd7\xb7\x40\x14\xfa\x9a\x4c\xa3\x79\x65\xa3\xd2\x9a\xf0\xf0\xa4\xcf\x7a\x16\x0e\xe3\xbe\x61\x87\xa3\x18\x49\x5e\x9c\x92\xb9\xac\xd3\x49\xcc\xe0\xb5\xab\xc1\xc3\x67\xa1\x29\x98\x1e\xc5\xc4\x18\x15\x0e\x8f\x0c\x3e\x1c\x59\xdb\x4d\xba\xbe\xa7\xdb\x9c\xf6\xae\xcc\x53\xfb\x0f\x55\xad\xcf\xe0\x2d\x71\xae\x75\xd8\x78\xcd\xf0\xa6\xc7\xf7\xd8\x69\x86\x1f\x0f\xbd\x49\x0e\x97\xf6\x80\x3f\xbb\x80\xe1\x88\xed\xd0\xde\x9d\xe1\x89\x60\x42\xe9\x4b\x7b\x2f\xc2\xe0\xc2\xed\xed\x7b\xc0\xc8\x2b\xb6\x89\xb8\x4f\x68\x94\x09\x8a\x0f\x8f\xa9\x93\xd1\xe1\x28\xd6\xf5\xa2\xe9\xfd\xc3\xcf\x7c\xb7\xd3\x12\x39\xb7\x3c\x0d\xe4\x67\xe9\xdf\x0a\x38\x2e\x01\xa2\x93\x92\xe1\x89\x98\xef\x04\xda\xd3\xec\x6f\xac\x72\xc7\x23\xff\x62\xe8\x1b\x6d\x2b\x20\xa6\x0b\x20\xb0\xc1\x85\x76\xbd\x39\x78\x4f\x76\x6f\x48\x9a\x37\x21\x2f\xbe\x7f\xd5\xbd\x0d\xe9\x3c\xdd\x16\x21\xdd\xf7\xf4\xf3\x77\x0d\x17\x3f\xdf\x6f\x36\x9b\x78\x25\xe5\x8a\x37\x1f\xee\xbb\x97\x11\xb6\x51\x8f\xef\x74\x00\x44\x6f\x45\x0e\x14\x97\xa8\xe6\x3d\xe6\xcd\x1b\x8a\x34\xf1\xdf\x9c\x93\xe6\xff\xd8\xfc\x27\x00\x00\xff\xff\xe5\xd8\xf8\x8e\x74\x23\x00\x00") func faucetHtmlBytes() ([]byte, error) { return bindataRead( @@ -84,8 +92,8 @@ func faucetHtml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "faucet.html", size: 9010, mode: os.FileMode(0644), modTime: time.Unix(1653732396, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb, 0xb7, 0xec, 0xe1, 0xa2, 0x8e, 0x94, 0xb, 0x2a, 0xc4, 0x21, 0x38, 0xa9, 0x6d, 0xdd, 0x31, 0x4, 0x3f, 0xa6, 0x26, 0xbe, 0x79, 0x11, 0xfc, 0xc0, 0x81, 0xe7, 0x85, 0x56, 0xec, 0x3, 0x77}} + info := bindataFileInfo{name: "faucet.html", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} return a, nil } @@ -93,8 +101,8 @@ func faucetHtml() (*asset, error) { // It returns an error if the asset could not be found or // could not be loaded. func Asset(name string) ([]byte, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { a, err := f() if err != nil { return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) @@ -104,12 +112,6 @@ func Asset(name string) ([]byte, error) { return nil, fmt.Errorf("Asset %s not found", name) } -// AssetString returns the asset contents as a string (instead of a []byte). -func AssetString(name string) (string, error) { - data, err := Asset(name) - return string(data), err -} - // MustAsset is like Asset but panics when Asset would return an error. // It simplifies safe initialization of global variables. func MustAsset(name string) []byte { @@ -121,18 +123,12 @@ func MustAsset(name string) []byte { return a } -// MustAssetString is like AssetString but panics when Asset would return an -// error. It simplifies safe initialization of global variables. -func MustAssetString(name string) string { - return string(MustAsset(name)) -} - // AssetInfo loads and returns the asset info for the given name. // It returns an error if the asset could not be found or // could not be loaded. func AssetInfo(name string) (os.FileInfo, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { a, err := f() if err != nil { return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) @@ -142,33 +138,6 @@ func AssetInfo(name string) (os.FileInfo, error) { return nil, fmt.Errorf("AssetInfo %s not found", name) } -// AssetDigest returns the digest of the file with the given name. It returns an -// error if the asset could not be found or the digest could not be loaded. -func AssetDigest(name string) ([sha256.Size]byte, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { - a, err := f() - if err != nil { - return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err) - } - return a.digest, nil - } - return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name) -} - -// Digests returns a map of all known files and their checksums. -func Digests() (map[string][sha256.Size]byte, error) { - mp := make(map[string][sha256.Size]byte, len(_bindata)) - for name := range _bindata { - a, err := _bindata[name]() - if err != nil { - return nil, err - } - mp[name] = a.digest - } - return mp, nil -} - // AssetNames returns the names of the assets. func AssetNames() []string { names := make([]string, 0, len(_bindata)) @@ -183,27 +152,26 @@ var _bindata = map[string]func() (*asset, error){ "faucet.html": faucetHtml, } -// AssetDebug is true if the assets were built with the debug flag enabled. -const AssetDebug = false - // AssetDir returns the file names below a certain // directory embedded in the file by go-bindata. // For example if you run go-bindata on data/... and data contains the // following hierarchy: -// data/ -// foo.txt -// img/ -// a.png -// b.png -// then AssetDir("data") would return []string{"foo.txt", "img"}, -// AssetDir("data/img") would return []string{"a.png", "b.png"}, -// AssetDir("foo.txt") and AssetDir("notexist") would return an error, and +// +// data/ +// foo.txt +// img/ +// a.png +// b.png +// +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("notexist") would return an error // AssetDir("") will return []string{"data"}. func AssetDir(name string) ([]string, error) { node := _bintree if len(name) != 0 { - canonicalName := strings.Replace(name, "\\", "/", -1) - pathList := strings.Split(canonicalName, "/") + cannonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(cannonicalName, "/") for _, p := range pathList { node = node.Children[p] if node == nil { @@ -230,7 +198,7 @@ var _bintree = &bintree{nil, map[string]*bintree{ "faucet.html": {faucetHtml, map[string]*bintree{}}, }} -// RestoreAsset restores an asset under the given directory. +// RestoreAsset restores an asset under the given directory func RestoreAsset(dir, name string) error { data, err := Asset(name) if err != nil { @@ -248,10 +216,14 @@ func RestoreAsset(dir, name string) error { if err != nil { return err } - return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + if err != nil { + return err + } + return nil } -// RestoreAssets restores an asset under the given directory recursively. +// RestoreAssets restores an asset under the given directory recursively func RestoreAssets(dir, name string) error { children, err := AssetDir(name) // File @@ -269,6 +241,6 @@ func RestoreAssets(dir, name string) error { } func _filePath(dir, name string) string { - canonicalName := strings.Replace(name, "\\", "/", -1) - return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...) + cannonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) } diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 47d333fed..1c37e00c4 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -311,6 +311,14 @@ func geth(ctx *cli.Context) error { defer stack.Close() startNode(ctx, stack, backend) + + log.Info("***************************** CONFIG INFO ****************************") + log.Info("******* FNCY_2.0", "chainId", backend.ChainConfig().ChainID) + log.Info("******* FNCY_2.0", "contract48kBlock", backend.ChainConfig().Contract48kBlock.Int64()) + log.Info("******* FNCY_2.0", "fncy2Block", backend.ChainConfig().Fncy2Block.Int64()) + log.Info("******* FNCY_2.0", "stopMintBlock", backend.ChainConfig().Parlia.StopMintBlock.Int64()) + log.Info("***************************** CONFIG INFO *****************************") + log.Info("Start FNCY_2.0 success") stack.Wait() return nil } diff --git a/consensus/parlia/abi.go b/consensus/parlia/abi.go index a0b49800c..7c0817b8b 100644 --- a/consensus/parlia/abi.go +++ b/consensus/parlia/abi.go @@ -2,544 +2,1051 @@ package parlia const validatorSetABI = ` [ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "batchTransfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "deprecatedDeposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address payable", - "name": "validator", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "directTransfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "systemTransfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "validatorDeposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "validatorFelony", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "validatorJailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "validatorMisdemeanor", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "validatorSetUpdated", - "type": "event" - }, - { - "inputs": [], - "name": "CHANNEL_ID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "DUSTY_INCOMING", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "EXTRA_FEE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "JAIL_MESSAGE_TYPE", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "RELAYER_REWARD", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "SYSTEM_ADDRESS", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VALIDATORS_UPDATE_MESSAGE_TYPE", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "alreadyInit", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "currentValidatorSet", - "outputs": [ - { - "internalType": "address", - "name": "consensusAddress", - "type": "address" - }, - { - "internalType": "address payable", - "name": "feeAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "BBCFeeAddress", - "type": "address" - }, - { - "internalType": "uint64", - "name": "votingPower", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "jailed", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "incoming", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "fromChainId", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "initLightClientAddr", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "initSlashContract", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "initSystemRewardAddr", - "outputs": [ - { - "internalType": "address payable", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "initTokenHubAddr", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "initValidatorSetBytes", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "keyPrefix", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "previousDepositHeight", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "sequence", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "toChainId", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalInComing", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "init", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "valAddr", - "type": "address" - } - ], - "name": "deposit", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "msgBytes", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "height", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "packageSequence", - "type": "uint64" - } - ], - "name": "update", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getValidators", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "getIncoming", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "misdemeanor", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "felony", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ] + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "staker", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + } + ], + "name": "Claimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "staker", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + } + ], + "name": "Delegated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "staker", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "dust", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + } + ], + "name": "Redelegated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ShareRewards", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "staker", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + } + ], + "name": "Undelegated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "status", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "commissionRate", + "type": "uint16" + } + ], + "name": "ValidatorAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + } + ], + "name": "ValidatorDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + } + ], + "name": "ValidatorJailed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "status", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "commissionRate", + "type": "uint16" + } + ], + "name": "ValidatorModified", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + } + ], + "name": "ValidatorOwnerClaimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + } + ], + "name": "ValidatorReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "ValidatorRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "slashes", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + } + ], + "name": "ValidatorSlashed", + "type": "event" + }, + { + "inputs": [], + "name": "init", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isInitialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "delayedInitializer", + "type": "bytes" + } + ], + "name": "useDelayedInitializer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "validators", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "owners", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "initialStakes", + "type": "uint256[]" + }, + { + "internalType": "uint16", + "name": "commissionRate", + "type": "uint16" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "getValidatorDelegation", + "outputs": [ + { + "internalType": "uint256", + "name": "delegatedAmount", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "atEpoch", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + } + ], + "name": "getValidatorStatus", + "outputs": [ + { + "internalType": "address", + "name": "ownerAddress", + "type": "address" + }, + { + "internalType": "uint8", + "name": "status", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "totalDelegated", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "slashesCount", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "changedAt", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "jailedBefore", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "claimedAt", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "commissionRate", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "totalRewards", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + }, + { + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + } + ], + "name": "getValidatorStatusAtEpoch", + "outputs": [ + { + "internalType": "address", + "name": "ownerAddress", + "type": "address" + }, + { + "internalType": "uint8", + "name": "status", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "totalDelegated", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "slashesCount", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "changedAt", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "jailedBefore", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "claimedAt", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "commissionRate", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "totalRewards", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "getValidatorByOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + } + ], + "name": "releaseValidatorFromJail", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + } + ], + "name": "forceUnJailValidator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + } + ], + "name": "delegate", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "undelegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "currentEpoch", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nextEpoch", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + }, + { + "internalType": "uint16", + "name": "commissionRate", + "type": "uint16" + } + ], + "name": "registerValidator", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "removeValidator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + } + ], + "name": "activateValidator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + } + ], + "name": "disableValidator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + }, + { + "internalType": "uint16", + "name": "commissionRate", + "type": "uint16" + } + ], + "name": "changeValidatorCommissionRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "changeValidatorOwner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "isValidatorActive", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "isValidator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getValidators", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockRewards", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasFee", + "type": "uint256" + } + ], + "name": "distributeRewards", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + } + ], + "name": "getValidatorFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + } + ], + "name": "getPendingValidatorFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + } + ], + "name": "claimValidatorFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "delegatorAddress", + "type": "address" + } + ], + "name": "getDelegatorFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "delegatorAddress", + "type": "address" + } + ], + "name": "getPendingDelegatorFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + } + ], + "name": "claimDelegatorFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "claimPendingUndelegates", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "calcAvailableForRedelegateAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "amountToStake", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardsDust", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "redelegateDelegatorFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validatorAddress", + "type": "address" + } + ], + "name": "slash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] ` const slashABI = ` diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index 9cb505e2e..9db67a943 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -1054,6 +1054,9 @@ func (p *Parlia) getCurrentValidators(blockHash common.Hash) ([]common.Address, } func (p *Parlia) BlockRewards(blockNumber *big.Int) *big.Int { if rules := p.chainConfig.Rules(blockNumber); rules.HasBlockRewards { + if p.chainConfig.Parlia.StopMintBlock != nil && p.chainConfig.Parlia.StopMintBlock.Cmp(blockNumber) <= 0 { + return nil + } blockRewards := p.chainConfig.Parlia.BlockRewards if blockRewards != nil && blockRewards.Cmp(common.Big0) > 0 { return blockRewards @@ -1070,17 +1073,21 @@ func (p *Parlia) distributeIncoming(val common.Address, state *state.StateDB, he state.SetBalance(consensus.SystemAddress, big.NewInt(0)) state.AddBalance(coinbase, balance) rewards := big.NewInt(0).Abs(balance) - if rules := p.chainConfig.Rules(header.Number); rules.HasBlockRewards { - blockRewards := p.chainConfig.Parlia.BlockRewards - // if we have enabled block rewards and rewards are greater than 0 then - if blockRewards != nil && blockRewards.Cmp(common.Big0) > 0 { - state.AddBalance(coinbase, blockRewards) - rewards = rewards.Add(rewards, blockRewards) - } + blockRewards := p.BlockRewards(header.Number) + if blockRewards != nil { + rewards = rewards.Add(rewards, blockRewards) + state.AddBalance(coinbase, blockRewards) } if rewards.Cmp(common.Big0) <= 0 { return nil } + if p.chainConfig.IsFncy2(header.Number) { + if blockRewards == nil { + blockRewards = big.NewInt(0) + } + log.Trace("fncy2 distribute to validator contract", "block hash", header.Hash(), "amount", rewards) + return p.distributeRewards(rewards, blockRewards, balance, val, state, header, chain, txs, receipts, receivedTxs, usedGas, mining) + } // remove 1/16 reward according to netmarble //doDistributeSysReward := state.GetBalance(common.HexToAddress(systemcontract.SystemRewardContract)).Cmp(maxSystemBalance) < 0 //if doDistributeSysReward { @@ -1160,6 +1167,27 @@ func (p *Parlia) distributeToSystem(amount *big.Int, state *state.StateDB, heade return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining) } +// slash spoiled validators +func (p *Parlia) distributeRewards(amount *big.Int, blockRewards *big.Int, gasFee *big.Int, validator common.Address, + state *state.StateDB, header *types.Header, chain core.ChainContext, + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error { + // method + method := "distributeRewards" + + // get packed data + data, err := p.validatorSetABI.Pack(method, + validator, blockRewards, gasFee, + ) + if err != nil { + log.Error("Unable to pack tx for distributeRewards", "error", err) + return err + } + // get system message + msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(systemcontract.ValidatorContract), data, amount) + // apply message + return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining) +} + // slash spoiled validators func (p *Parlia) distributeToValidator(amount *big.Int, validator common.Address, state *state.StateDB, header *types.Header, chain core.ChainContext, diff --git a/core/state_transition.go b/core/state_transition.go index e71b98075..636c90636 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -39,8 +39,10 @@ The state transitioning model does all the necessary work to work out a valid ne 3) Create a new state object if the recipient is \0*32 4) Value transfer == If contract creation == - 4a) Attempt to run transaction data - 4b) If valid, use result as code for the new state object + + 4a) Attempt to run transaction data + 4b) If valid, use result as code for the new state object + == end == 5) Run Script section 6) Derive new state root @@ -213,13 +215,13 @@ func (st *StateTransition) preCheck() error { // TransitionDb will transition the state by applying the current message and // returning the evm execution result with following fields. // -// - used gas: -// total gas used (including gas being refunded) -// - returndata: -// the returned data from evm -// - concrete execution error: -// various **EVM** error which aborts the execution, -// e.g. ErrOutOfGas, ErrExecutionReverted +// - used gas: +// total gas used (including gas being refunded) +// - returndata: +// the returned data from evm +// - concrete execution error: +// various **EVM** error which aborts the execution, +// e.g. ErrOutOfGas, ErrExecutionReverted // // However if any consensus issue encountered, return the error directly with // nil evm execution result. @@ -238,6 +240,14 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) { if err := st.preCheck(); err != nil { return nil, err } + + if st.evm.VmConfig.Debug { + st.evm.VmConfig.Tracer.CaptureTxStart(st.initialGas) + defer func() { + st.evm.VmConfig.Tracer.CaptureTxEnd(st.gas) + }() + } + msg := st.msg sender := vm.AccountRef(msg.From()) homestead := st.evm.ChainConfig().IsHomestead(st.evm.Context.BlockNumber) diff --git a/core/tx_pool.go b/core/tx_pool.go index ba073a29a..954c75cb1 100644 --- a/core/tx_pool.go +++ b/core/tx_pool.go @@ -253,6 +253,7 @@ type TxPool struct { gasFreeAddressMap map[common.Address]uint // from address that can join tx_pool for free gasFreeAddressMapFunc func(common.Hash) (map[common.Address]uint, error) // add func to get gasFreeAddressMap + gasPriceFunc func(common.Hash) (*big.Int, error) // add func to get gas price, do nothing when return 0 pending map[common.Address]*txList // All currently processable transactions queue map[common.Address]*txList // Queued but non-processable transactions @@ -283,11 +284,17 @@ func getNoGasFreeAddressMapFunc() func(common.Hash) (map[common.Address]uint, er return gasFreeToAddressMap, nil } } +func getGasPriceFunc() func(common.Hash) (*big.Int, error) { + return func(blockHash common.Hash) (*big.Int, error) { + return big.NewInt(0), nil + } +} + func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain blockChain) *TxPool { - return NewEnhanceTxPool(config, chainconfig, chain, getNoGasFreeAddressMapFunc()) + return NewEnhanceTxPool(config, chainconfig, chain, getNoGasFreeAddressMapFunc(), getGasPriceFunc()) } -func NewEnhanceTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain blockChain, gasFreeAddressMapFunc func(common.Hash) (map[common.Address]uint, error)) *TxPool { +func NewEnhanceTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain blockChain, gasFreeAddressMapFunc func(common.Hash) (map[common.Address]uint, error), gasPriceFunc func(common.Hash) (*big.Int, error)) *TxPool { // Sanitize the input to ensure no vulnerable gas prices are set config = (&config).sanitize() // Create the transaction pool with its initial settings @@ -309,6 +316,7 @@ func NewEnhanceTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chai gasPrice: new(big.Int).SetUint64(config.PriceLimit), gasFreeAddressMap: make(map[common.Address]uint), gasFreeAddressMapFunc: gasFreeAddressMapFunc, + gasPriceFunc: gasPriceFunc, } pool.locals = newAccountSet(pool.signer) for _, addr := range config.Locals { @@ -479,10 +487,19 @@ func (pool *TxPool) SubscribeReannoTxsEvent(ch chan<- ReannoTxsEvent) event.Subs func (pool *TxPool) GasPrice() *big.Int { pool.mu.RLock() defer pool.mu.RUnlock() + return new(big.Int).Set(pool.gasPrice) +} +//Fncy2 Update +func (pool *TxPool) GasPriceWithoutLock() *big.Int { return new(big.Int).Set(pool.gasPrice) } +func (pool *TxPool) SetGasPriceWithoutLock(price *big.Int) { + pool.gasPrice = price + log.Info("Transaction pool price threshold updated", "price", price) +} + // SetGasPrice updates the minimum price required by the transaction pool for a // new transaction, and drops all transactions below this threshold. func (pool *TxPool) SetGasPrice(price *big.Int) { @@ -551,7 +568,6 @@ func (pool *TxPool) Content() (map[common.Address]types.Transactions, map[common func (pool *TxPool) Pending() (map[common.Address]types.Transactions, error) { pool.mu.Lock() defer pool.mu.Unlock() - pending := make(map[common.Address]types.Transactions) for addr, list := range pool.pending { pending[addr] = list.Flatten() @@ -1293,6 +1309,21 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) { next := new(big.Int).Add(newHead.Number, big.NewInt(1)) pool.istanbul = pool.chainconfig.IsIstanbul(next) pool.eip2718 = pool.chainconfig.IsBerlin(next) + //fncy2 update + if pool.chainconfig.IsFncy2(next) { + gasPrice, err := pool.gasPriceFunc(pool.chain.CurrentBlock().Hash()) + if err != nil { + log.Warn("Failed to get gasPrice", "err", err) + } else { + if gasPrice != nil && gasPrice.Cmp(common.Big0) > 0 { + if pool.gasPrice == nil || pool.gasPrice.Cmp(gasPrice) != 0 { + log.Debug("Set gasPrice ", " old gasPrice", pool.gasPrice, " new gasPrice", gasPrice) + pool.SetGasPriceWithoutLock(gasPrice) + } + } + } + } + } // promoteExecutables moves transactions that have become processable from the diff --git a/core/vm/access_list_tracer.go b/core/vm/access_list_tracer.go index d7993b4f7..3f79d6d5a 100644 --- a/core/vm/access_list_tracer.go +++ b/core/vm/access_list_tracer.go @@ -180,3 +180,12 @@ func (a *AccessListTracer) AccessList() types.AccessList { func (a *AccessListTracer) Equal(other *AccessListTracer) bool { return a.list.equal(other.list) } + +// CaptureTxStart implements the Tracer interface and is invoked at the beginning of +// transaction processing. +func (t *AccessListTracer) CaptureTxStart(gasLimit uint64) { +} + +// CaptureTxStart implements the Tracer interface and is invoked at the end of +// transaction processing. +func (t *AccessListTracer) CaptureTxEnd(restGas uint64) {} diff --git a/core/vm/evm.go b/core/vm/evm.go index e24212105..06cf98e08 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -134,7 +134,7 @@ type EVM struct { chainRules params.Rules // virtual machine configuration options used to initialise the // evm. - vmConfig Config + VmConfig Config // global (to this context) ethereum virtual machine // used throughout the execution of the tx. interpreters []Interpreter @@ -155,7 +155,7 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig evm.Context = blockCtx evm.TxContext = txCtx evm.StateDB = statedb - evm.vmConfig = vmConfig + evm.VmConfig = vmConfig evm.chainConfig = chainConfig evm.chainRules = chainConfig.Rules(blockCtx.BlockNumber) evm.interpreters = make([]Interpreter, 0, 1) @@ -215,7 +215,7 @@ func (evm *EVM) Interpreter() Interpreter { // the necessary steps to create accounts and reverses the state in case of an // execution error or failed value transfer. func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) { - if evm.vmConfig.NoRecursion && evm.depth > 0 { + if evm.VmConfig.NoRecursion && evm.depth > 0 { return nil, gas, nil } // Fail if we're trying to execute above the call depth limit @@ -232,13 +232,13 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas if !evm.StateDB.Exist(addr) { if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 { // Calling a non existing account, don't do anything, but ping the tracer - if evm.vmConfig.Debug { + if evm.VmConfig.Debug { if evm.depth == 0 { - evm.vmConfig.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value) - evm.vmConfig.Tracer.CaptureEnd(ret, 0, 0, nil) + evm.VmConfig.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value) + evm.VmConfig.Tracer.CaptureEnd(ret, 0, 0, nil) } else { - evm.vmConfig.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value) - evm.vmConfig.Tracer.CaptureExit(ret, 0, nil) + evm.VmConfig.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value) + evm.VmConfig.Tracer.CaptureExit(ret, 0, nil) } } return nil, gas, nil @@ -248,17 +248,17 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas evm.Context.Transfer(evm.StateDB, caller.Address(), addr, value) // Capture the tracer start/end events in debug mode - if evm.vmConfig.Debug { + if evm.VmConfig.Debug { if evm.depth == 0 { - evm.vmConfig.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value) + evm.VmConfig.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value) defer func(startGas uint64, startTime time.Time) { // Lazy evaluation of the parameters - evm.vmConfig.Tracer.CaptureEnd(ret, startGas-gas, time.Since(startTime), err) + evm.VmConfig.Tracer.CaptureEnd(ret, startGas-gas, time.Since(startTime), err) }(gas, time.Now()) } else { // Handle tracer events for entering and exiting a call frame - evm.vmConfig.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value) + evm.VmConfig.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value) defer func(startGas uint64) { - evm.vmConfig.Tracer.CaptureExit(ret, startGas-gas, err) + evm.VmConfig.Tracer.CaptureExit(ret, startGas-gas, err) }(gas) } } @@ -304,7 +304,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas // CallCode differs from Call in the sense that it executes the given address' // code with the caller as context. func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) { - if evm.vmConfig.NoRecursion && evm.depth > 0 { + if evm.VmConfig.NoRecursion && evm.depth > 0 { return nil, gas, nil } // Fail if we're trying to execute above the call depth limit @@ -321,10 +321,10 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, var snapshot = evm.StateDB.Snapshot() // Invoke tracer hooks that signal entering/exiting a call frame - if evm.vmConfig.Debug { - evm.vmConfig.Tracer.CaptureEnter(CALLCODE, caller.Address(), addr, input, gas, value) + if evm.VmConfig.Debug { + evm.VmConfig.Tracer.CaptureEnter(CALLCODE, caller.Address(), addr, input, gas, value) defer func(startGas uint64) { - evm.vmConfig.Tracer.CaptureExit(ret, startGas-gas, err) + evm.VmConfig.Tracer.CaptureExit(ret, startGas-gas, err) }(gas) } @@ -355,7 +355,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, // DelegateCall differs from CallCode in the sense that it executes the given address' // code with the caller as context and the caller is set to the caller of the caller. func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { - if evm.vmConfig.NoRecursion && evm.depth > 0 { + if evm.VmConfig.NoRecursion && evm.depth > 0 { return nil, gas, nil } // Fail if we're trying to execute above the call depth limit @@ -365,10 +365,10 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by var snapshot = evm.StateDB.Snapshot() // Invoke tracer hooks that signal entering/exiting a call frame - if evm.vmConfig.Debug { - evm.vmConfig.Tracer.CaptureEnter(DELEGATECALL, caller.Address(), addr, input, gas, nil) + if evm.VmConfig.Debug { + evm.VmConfig.Tracer.CaptureEnter(DELEGATECALL, caller.Address(), addr, input, gas, nil) defer func(startGas uint64) { - evm.vmConfig.Tracer.CaptureExit(ret, startGas-gas, err) + evm.VmConfig.Tracer.CaptureExit(ret, startGas-gas, err) }(gas) } @@ -397,7 +397,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by // Opcodes that attempt to perform such modifications will result in exceptions // instead of performing the modifications. func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { - if evm.vmConfig.NoRecursion && evm.depth > 0 { + if evm.VmConfig.NoRecursion && evm.depth > 0 { return nil, gas, nil } // Fail if we're trying to execute above the call depth limit @@ -418,10 +418,10 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte evm.StateDB.AddBalance(addr, big0) // Invoke tracer hooks that signal entering/exiting a call frame - if evm.vmConfig.Debug { - evm.vmConfig.Tracer.CaptureEnter(STATICCALL, caller.Address(), addr, input, gas, nil) + if evm.VmConfig.Debug { + evm.VmConfig.Tracer.CaptureEnter(STATICCALL, caller.Address(), addr, input, gas, nil) defer func(startGas uint64) { - evm.vmConfig.Tracer.CaptureExit(ret, startGas-gas, err) + evm.VmConfig.Tracer.CaptureExit(ret, startGas-gas, err) }(gas) } @@ -498,15 +498,15 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, contract := NewContract(caller, AccountRef(address), value, gas) contract.SetCodeOptionalHash(&address, codeAndHash) - if evm.vmConfig.NoRecursion && evm.depth > 0 { + if evm.VmConfig.NoRecursion && evm.depth > 0 { return nil, address, gas, nil } - if evm.vmConfig.Debug { + if evm.VmConfig.Debug { if evm.depth == 0 { - evm.vmConfig.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value) + evm.VmConfig.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value) } else { - evm.vmConfig.Tracer.CaptureEnter(typ, caller.Address(), address, codeAndHash.code, gas, value) + evm.VmConfig.Tracer.CaptureEnter(typ, caller.Address(), address, codeAndHash.code, gas, value) } } @@ -515,7 +515,11 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, ret, err := run(evm, contract, nil, false) // Check whether the max code size has been exceeded, assign err if the case. - if err == nil && evm.chainRules.IsEIP158 && len(ret) > params.MaxCodeSize { + maxCodeSize := params.MaxCodeSize + if evm.chainRules.IsContract48kBlock { + maxCodeSize = params.MaxCodeSize * 2 + } + if err == nil && evm.chainRules.IsEIP158 && len(ret) > maxCodeSize { err = ErrMaxCodeSizeExceeded } @@ -542,11 +546,11 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, } } - if evm.vmConfig.Debug { + if evm.VmConfig.Debug { if evm.depth == 0 { - evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err) + evm.VmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err) } else { - evm.vmConfig.Tracer.CaptureExit(ret, gas-contract.Gas, err) + evm.VmConfig.Tracer.CaptureExit(ret, gas-contract.Gas, err) } } return ret, address, contract.Gas, err diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 0ecf28d59..68571ebd4 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -244,7 +244,7 @@ func opSha3(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byt interpreter.hasher.Read(interpreter.hasherBuf[:]) evm := interpreter.evm - if evm.vmConfig.EnablePreimageRecording { + if evm.VmConfig.EnablePreimageRecording { evm.StateDB.AddPreimage(interpreter.hasherBuf, data) } @@ -390,16 +390,21 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) // opExtCodeHash returns the code hash of a specified account. // There are several cases when the function is called, while we can relay everything // to `state.GetCodeHash` function to ensure the correctness. -// (1) Caller tries to get the code hash of a normal contract account, state +// +// (1) Caller tries to get the code hash of a normal contract account, state +// // should return the relative code hash and set it as the result. // -// (2) Caller tries to get the code hash of a non-existent account, state should +// (2) Caller tries to get the code hash of a non-existent account, state should +// // return common.Hash{} and zero will be set as the result. // -// (3) Caller tries to get the code hash for an account without contract code, +// (3) Caller tries to get the code hash for an account without contract code, +// // state should return emptyCodeHash(0xc5d246...) as the result. // -// (4) Caller tries to get the code hash of a precompiled account, the result +// (4) Caller tries to get the code hash of a precompiled account, the result +// // should be zero or emptyCodeHash. // // It is worth noting that in order to avoid unnecessary create and clean, @@ -408,10 +413,12 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) // If the precompile account is not transferred any amount on a private or // customized chain, the return value will be zero. // -// (5) Caller tries to get the code hash for an account which is marked as suicided +// (5) Caller tries to get the code hash for an account which is marked as suicided +// // in the current transaction, the code hash of this account should be returned. // -// (6) Caller tries to get the code hash for an account which is marked as deleted, +// (6) Caller tries to get the code hash for an account which is marked as deleted, +// // this account should be regarded as a non-existent account and zero should be returned. func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { slot := scope.Stack.peek() diff --git a/core/vm/logger.go b/core/vm/logger.go index f8f08e726..131f83213 100644 --- a/core/vm/logger.go +++ b/core/vm/logger.go @@ -105,6 +105,10 @@ func (s *StructLog) ErrorString() string { // Note that reference types are actual VM data structures; make copies // if you need to retain them beyond the current call. type EVMLogger interface { + // Transaction level + CaptureTxStart(gasLimit uint64) + CaptureTxEnd(restGas uint64) + CaptureStart(env *EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) CaptureState(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error) CaptureEnter(typ OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) @@ -147,6 +151,10 @@ func (l *StructLogger) Reset() { l.err = nil } +func (*StructLogger) CaptureTxStart(gasLimit uint64) {} + +func (*StructLogger) CaptureTxEnd(restGas uint64) {} + // CaptureStart implements the EVMLogger interface to initialize the tracing operation. func (l *StructLogger) CaptureStart(env *EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { l.env = env @@ -307,6 +315,15 @@ func NewMarkdownLogger(cfg *LogConfig, writer io.Writer) *mdLogger { return l } +// CaptureTxStart implements the Tracer interface and is invoked at the beginning of +// transaction processing. +func (t *mdLogger) CaptureTxStart(gasLimit uint64) { +} + +// CaptureTxStart implements the Tracer interface and is invoked at the end of +// transaction processing. +func (t *mdLogger) CaptureTxEnd(restGas uint64) {} + func (t *mdLogger) CaptureStart(env *EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { t.env = env if !create { diff --git a/core/vm/logger_json.go b/core/vm/logger_json.go index c249dba7e..8c4fbf3dc 100644 --- a/core/vm/logger_json.go +++ b/core/vm/logger_json.go @@ -42,6 +42,15 @@ func NewJSONLogger(cfg *LogConfig, writer io.Writer) *JSONLogger { return l } +// CaptureTxStart implements the Tracer interface and is invoked at the beginning of +// transaction processing. +func (t *JSONLogger) CaptureTxStart(gasLimit uint64) { +} + +// CaptureTxStart implements the Tracer interface and is invoked at the end of +// transaction processing. +func (t *JSONLogger) CaptureTxEnd(restGas uint64) {} + func (l *JSONLogger) CaptureStart(env *EVM, from, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { l.env = env } diff --git a/eth/abi.go b/eth/abi.go index c76b58bc3..1033c3f66 100644 --- a/eth/abi.go +++ b/eth/abi.go @@ -21,6 +21,25 @@ const chainConfigABI = ` "name": "ActiveValidatorsLengthChanged", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "share", + "type": "uint16" + } + ], + "name": "DistributeRewardsShareChanged", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -78,6 +97,25 @@ const chainConfigABI = ` "name": "FelonyThresholdChanged", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "preValue", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newValue", + "type": "address" + } + ], + "name": "FoundationAddressChanged", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -142,6 +180,25 @@ const chainConfigABI = ` "name": "FreeGasAddressSizeChanged", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "preValue", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newValue", + "type": "uint256" + } + ], + "name": "GasPriceChanged", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -250,6 +307,19 @@ const chainConfigABI = ` "name": "ValidatorJailEpochLengthChanged", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "share", + "type": "uint16" + } + ], + "name": "ValidatorRewardsShareChanged", + "type": "event" + }, { "inputs": [], "name": "freeGasAddressAdmin", @@ -711,6 +781,111 @@ const chainConfigABI = ` "outputs": [], "stateMutability": "nonpayable", "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newValue", + "type": "uint256" + } + ], + "name": "setGasPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getGasPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getDistributeRewardsShares", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + }, + { + "components": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint16", + "name": "share", + "type": "uint16" + } + ], + "internalType": "struct IChainConfig.DistributeRewardsShare[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "validatorShare", + "type": "uint16" + }, + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "uint16[]", + "name": "shares", + "type": "uint16[]" + } + ], + "name": "updateDistributeRewardsShares", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newValue", + "type": "address" + } + ], + "name": "setFoundationAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getFoundationAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" } ] ` diff --git a/eth/api_backend.go b/eth/api_backend.go index daf6c19ec..2cf670831 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -19,6 +19,7 @@ package eth import ( "context" "errors" + "github.com/ethereum/go-ethereum/log" "math/big" "github.com/ethereum/go-ethereum/accounts" @@ -276,6 +277,21 @@ func (b *EthAPIBackend) Downloader() *downloader.Downloader { } func (b *EthAPIBackend) SuggestPrice(ctx context.Context) (*big.Int, error) { + //Fncy2 Update + if b.ChainConfig().IsFncy2(b.Chain().CurrentBlock().Header().Number) { + suggestPrice, err := b.gpo.SuggestPrice(ctx) + gasPrice := b.eth.TxPool().GasPriceWithoutLock() + log.Debug("suggestPrice", "gpo.SuggestPrice", suggestPrice, "gasPrice", gasPrice) + if err == nil { + if suggestPrice.Cmp(gasPrice) < 0 { + return gasPrice, nil + } + return suggestPrice, nil + } else { + log.Warn("gpo.SuggestPrice ", "error ", err) + return gasPrice, nil + } + } return b.gpo.SuggestPrice(ctx) } diff --git a/eth/backend.go b/eth/backend.go index 7aafbe28e..acafba7d9 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -64,6 +64,8 @@ import ( "github.com/ethereum/go-ethereum/rpc" ) +var maxPrice = big.NewInt(1200000 * params.GWei) + // Config contains the configuration options of the ETH protocol. // Deprecated: use ethconfig.Config instead. type Config = ethconfig.Config @@ -225,7 +227,8 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { if config.TxPool.Journal != "" { config.TxPool.Journal = stack.ResolvePath(config.TxPool.Journal) } - eth.txPool = core.NewEnhanceTxPool(config.TxPool, chainConfig, eth.blockchain, getCurrentGasFreeAddressMapFunc(ethAPI)) + //getCurrentGasPriceFunc + eth.txPool = core.NewEnhanceTxPool(config.TxPool, chainConfig, eth.blockchain, getCurrentGasFreeAddressMapFunc(ethAPI), getCurrentGasPriceFunc(eth, ethAPI)) // Permit the downloader to use the trie cache allowance during fast sync cacheLimit := cacheConfig.TrieCleanLimit + cacheConfig.TrieDirtyLimit + cacheConfig.SnapshotLimit @@ -599,6 +602,59 @@ func (s *Ethereum) Stop() error { return nil } +func getCurrentGasPriceFunc(eth *Ethereum, ee *ethapi.PublicBlockChainAPI) func(common.Hash) (*big.Int, error) { + return func(blockHash common.Hash) (*big.Int, error) { + // block + blockNr := rpc.BlockNumberOrHashWithHash(blockHash, false) + // method + method := "getGasPrice" + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() // cancel when we are finished consuming integers + chainConfig, err := abi.JSON(strings.NewReader(chainConfigABI)) + if err != nil { + log.Error("Unable to abi.JSON for getGasPrice", "error", err) + return nil, err + } + data, err := chainConfig.Pack(method) + if err != nil { + log.Error("Unable to pack tx for getGasPrice", "error", err) + return nil, err + } + // call + msgData := (hexutil.Bytes)(data) + toAddress := common.HexToAddress(systemcontract.ChainConfigContract) + gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2)) + result, err := ee.Call(ctx, ethapi.CallArgs{ + Gas: &gas, + To: &toAddress, + Data: &msgData, + }, blockNr, nil) + if err != nil { + return nil, err + } + gasPrice := big.NewInt(0) + if err := chainConfig.UnpackIntoInterface(&gasPrice, method, result); err != nil { + return nil, err + } + if gasPrice != nil && gasPrice.Cmp(common.Big0) > 0 { + if eth.APIBackend.gpo != nil { + if eth.APIBackend.gpo.GetDefaultPrice() == nil || eth.APIBackend.gpo.GetDefaultPrice().Cmp(gasPrice) != 0 { + eth.APIBackend.gpo.SetDefaultPrice(gasPrice) + } + if eth.APIBackend.gpo.GetMaxPrice() == nil || eth.APIBackend.gpo.GetMaxPrice().Cmp(maxPrice) != 0 { + eth.APIBackend.gpo.SetMaxPrice(maxPrice) + } + } + if eth.gasPrice == nil || eth.gasPrice.Cmp(gasPrice) != 0 { + eth.lock.Lock() + eth.gasPrice = gasPrice + eth.lock.Unlock() + } + } + return gasPrice, nil + } +} // getCurrentGasFreeAddressMapFunc get current GasFreeAddressMapFunc func getCurrentGasFreeAddressMapFunc(ee *ethapi.PublicBlockChainAPI) func(common.Hash) (map[common.Address]uint, error) { diff --git a/eth/gasprice/gasprice.go b/eth/gasprice/gasprice.go index bc8fa81a4..881ed422f 100644 --- a/eth/gasprice/gasprice.go +++ b/eth/gasprice/gasprice.go @@ -98,6 +98,20 @@ func NewOracle(backend OracleBackend, params Config) *Oracle { } } +func (gpo *Oracle) SetDefaultPrice(defaultPrice *big.Int) { + gpo.defaultPrice = defaultPrice +} +func (gpo *Oracle) GetDefaultPrice() *big.Int { + return gpo.defaultPrice +} + +func (gpo *Oracle) SetMaxPrice(maxPrice *big.Int) { + gpo.maxPrice = maxPrice +} +func (gpo *Oracle) GetMaxPrice() *big.Int { + return gpo.maxPrice +} + // SuggestPrice returns a gasprice so that newly created transaction can // have a very high chance to be included in the following blocks. func (gpo *Oracle) SuggestPrice(ctx context.Context) (*big.Int, error) { diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 8df152fd0..0e1f1b3f2 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -20,6 +20,7 @@ import ( "bufio" "bytes" "context" + "encoding/json" "errors" "fmt" "io/ioutil" @@ -172,6 +173,8 @@ type TraceConfig struct { Tracer *string Timeout *string Reexec *uint64 + + TracerConfig json.RawMessage } // TraceCallConfig is the config for traceCall API. It holds one more @@ -935,7 +938,7 @@ func (api *API) traceTx(ctx context.Context, message core.Message, txctx *Contex return nil, err } } - if t, err := New(*config.Tracer, txctx); err != nil { + if t, err := New(*config.Tracer, txctx, config.TracerConfig); err != nil { return nil, err } else { deadlineCtx, cancel := context.WithTimeout(ctx, timeout) diff --git a/eth/tracers/js/tracer.go b/eth/tracers/js/tracer.go index b8e035e6f..399aeb8dd 100644 --- a/eth/tracers/js/tracer.go +++ b/eth/tracers/js/tracer.go @@ -424,7 +424,7 @@ type jsTracer struct { // New instantiates a new tracer instance. code specifies a Javascript snippet, // which must evaluate to an expression returning an object with 'step', 'fault' // and 'result' functions. -func newJsTracer(code string, ctx *tracers2.Context) (tracers2.Tracer, error) { +func newJsTracer(code string, ctx *tracers2.Context, cfg json.RawMessage) (tracers2.Tracer, error) { if c, ok := assetTracers[code]; ok { code = c } @@ -679,6 +679,15 @@ func wrapError(context string, err error) error { return fmt.Errorf("%v in server-side tracer function '%v'", err, context) } +// CaptureTxStart implements the Tracer interface and is invoked at the beginning of +// transaction processing. +func (jst *jsTracer) CaptureTxStart(gasLimit uint64) { +} + +// CaptureTxStart implements the Tracer interface and is invoked at the end of +// transaction processing. +func (t *jsTracer) CaptureTxEnd(restGas uint64) {} + // CaptureStart implements the Tracer interface to initialize the tracing operation. func (jst *jsTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { jst.env = env diff --git a/eth/tracers/native/call.go b/eth/tracers/native/call.go index 16ea75aa4..0804db9a0 100644 --- a/eth/tracers/native/call.go +++ b/eth/tracers/native/call.go @@ -56,13 +56,22 @@ type callTracer struct { // newCallTracer returns a native go tracer which tracks // call frames of a tx, and implements vm.EVMLogger. -func newCallTracer() tracers.Tracer { +func newCallTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, error) { // First callframe contains tx context info // and is populated on start and end. t := &callTracer{callstack: make([]callFrame, 1)} - return t + return t, nil } +// CaptureTxStart implements the Tracer interface and is invoked at the beginning of +// transaction processing. +func (t *callTracer) CaptureTxStart(gasLimit uint64) { +} + +// CaptureTxStart implements the Tracer interface and is invoked at the end of +// transaction processing. +func (t *callTracer) CaptureTxEnd(restGas uint64) {} + // CaptureStart implements the EVMLogger interface to initialize the tracing operation. func (t *callTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { t.env = env diff --git a/eth/tracers/native/noop.go b/eth/tracers/native/noop.go index ee110ef7d..65ccd7017 100644 --- a/eth/tracers/native/noop.go +++ b/eth/tracers/native/noop.go @@ -35,8 +35,14 @@ func init() { type noopTracer struct{} // newNoopTracer returns a new noop tracer. -func newNoopTracer() tracers.Tracer { - return &noopTracer{} +func newNoopTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, error) { + return &noopTracer{}, nil +} + +func (l *noopTracer) CaptureTxStart(gasLimit uint64) { +} + +func (l *noopTracer) CaptureTxEnd(restGas uint64) { } // CaptureStart implements the EVMLogger interface to initialize the tracing operation. diff --git a/eth/tracers/native/prestate.go b/eth/tracers/native/prestate.go new file mode 100644 index 000000000..fe4866e26 --- /dev/null +++ b/eth/tracers/native/prestate.go @@ -0,0 +1,276 @@ +// Copyright 2022 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package native + +import ( + "encoding/json" + "github.com/ethereum/go-ethereum/common/hexutil" + "math/big" + "sync/atomic" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/eth/tracers" +) + +func init() { + register("stateDiff", newStateDiffTracer) +} + +type state = map[common.Address]account +type account struct { + Balance string `json:"balance,omitempty"` + Nonce uint64 `json:"nonce,omitempty"` + storage map[common.Hash]common.Hash +} + +func (a account) exists() bool { + bi := new(big.Int) + bi.SetString(a.Balance[2:], 16) + return a.Nonce > 0 || (bi.Sign() != 0) +} + +type stateDiffTracer struct { + env *vm.EVM + pre state + post state + create bool + to common.Address + gasLimit uint64 // Amount of gas bought for the whole tx + interrupt uint32 // Atomic flag to signal execution interruption + reason error // Textual reason for the interruption + + config stateDiffTracerConfig + created map[common.Address]bool + deleted map[common.Address]bool +} + +type stateDiffTracerConfig struct { + DiffMode bool `json:"diffMode"` // If true, this tracer will return state modifications +} + +func newStateDiffTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, error) { + var config stateDiffTracerConfig + if cfg != nil { + if err := json.Unmarshal(cfg, &config); err != nil { + return nil, err + } + } + // and is populated on start and end. + return &stateDiffTracer{ + pre: state{}, + post: state{}, + config: config, + created: make(map[common.Address]bool), + deleted: make(map[common.Address]bool), + }, nil +} + +// CaptureStart implements the EVMLogger interface to initialize the tracing operation. +func (t *stateDiffTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { + t.env = env + t.create = create + t.to = to + + t.lookupAccount(from) + t.lookupAccount(to) + t.lookupAccount(env.Context.Coinbase) + //t.lookupAccount(consensus.SystemAddress) + + // The recipient balance includes the value transferred. + toAccount := t.pre[to] + toBal := hexutil.MustDecodeBig(toAccount.Balance) + toBal = new(big.Int).Sub(toBal, value) + toAccount.Balance = hexutil.EncodeBig(toBal) + t.pre[to] = toAccount + + // The sender balance is after reducing: value and gasLimit. + // We need to re-add them to get the pre-tx balance. + fromAccount := t.pre[from] + fromBal := hexutil.MustDecodeBig(fromAccount.Balance) + gasPrice := env.TxContext.GasPrice + consumedGas := new(big.Int).Mul(gasPrice, new(big.Int).SetUint64(t.gasLimit)) + fromBal.Add(fromBal, new(big.Int).Add(value, consumedGas)) + fromAccount.Balance = hexutil.EncodeBig(fromBal) + fromAccount.Nonce-- + t.pre[from] = fromAccount + + if create && t.config.DiffMode { + t.created[to] = true + } +} + +// CaptureEnd is called after the call finishes to finalize the tracing. +func (t *stateDiffTracer) CaptureEnd(output []byte, gasUsed uint64, _ time.Duration, err error) { + if t.config.DiffMode { + return + } + + if t.create { + // Keep existing account prior to contract creation at that address + if s := t.pre[t.to]; !s.exists() { + // Exclude newly created contract. + delete(t.pre, t.to) + } + } +} + +// CaptureState implements the EVMLogger interface to trace a single step of VM execution. +func (t *stateDiffTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) { + stack := scope.Stack + stackData := stack.Data() + stackLen := len(stackData) + caller := scope.Contract.Address() + switch { + case stackLen >= 1 && (op == vm.SLOAD || op == vm.SSTORE): + slot := common.Hash(stackData[stackLen-1].Bytes32()) + t.lookupStorage(caller, slot) + case stackLen >= 1 && (op == vm.EXTCODECOPY || op == vm.EXTCODEHASH || op == vm.EXTCODESIZE || op == vm.BALANCE || op == vm.SELFDESTRUCT): + addr := common.Address(stackData[stackLen-1].Bytes20()) + t.lookupAccount(addr) + if op == vm.SELFDESTRUCT { + t.deleted[caller] = true + } + case stackLen >= 5 && (op == vm.DELEGATECALL || op == vm.CALL || op == vm.STATICCALL || op == vm.CALLCODE): + addr := common.Address(stackData[stackLen-2].Bytes20()) + t.lookupAccount(addr) + case op == vm.CREATE: + nonce := t.env.StateDB.GetNonce(caller) + addr := crypto.CreateAddress(caller, nonce) + t.lookupAccount(addr) + t.created[addr] = true + case stackLen >= 4 && op == vm.CREATE2: + offset := stackData[stackLen-2] + size := stackData[stackLen-3] + init := scope.Memory.GetCopy(int64(offset.Uint64()), int64(size.Uint64())) + inithash := crypto.Keccak256(init) + salt := stackData[stackLen-4] + addr := crypto.CreateAddress2(caller, salt.Bytes32(), inithash) + t.lookupAccount(addr) + t.created[addr] = true + } +} + +// CaptureFault implements the EVMLogger interface to trace an execution fault. +func (t *stateDiffTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, _ *vm.ScopeContext, depth int, err error) { +} + +// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct). +func (t *stateDiffTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { +} + +// CaptureExit is called when EVM exits a scope, even if the scope didn't +// execute any code. +func (t *stateDiffTracer) CaptureExit(output []byte, gasUsed uint64, err error) { +} + +func (t *stateDiffTracer) CaptureTxStart(gasLimit uint64) { + t.gasLimit = gasLimit +} + +func (t *stateDiffTracer) CaptureTxEnd(restGas uint64) { + if !t.config.DiffMode { + return + } + + //for addr, state := range t.pre { + for addr, _ := range t.pre { + // The deleted account's state is pruned from `post` but kept in `pre` + if _, ok := t.deleted[addr]; ok { + continue + } + modified := false + postAccount := account{storage: make(map[common.Hash]common.Hash)} + newBalance := bigToHex(t.env.StateDB.GetBalance(addr)) + newNonce := t.env.StateDB.GetNonce(addr) + //newCode := t.env.StateDB.GetCode(addr) + + if newBalance != t.pre[addr].Balance { + modified = true + postAccount.Balance = newBalance + } + if newNonce != t.pre[addr].Nonce { + modified = true + postAccount.Nonce = newNonce + } + + if modified { + t.post[addr] = postAccount + } else { + // if state is not modified, then no need to include into the pre state + delete(t.pre, addr) + } + } + // the new created contracts' prestate were empty, so delete them + for a := range t.created { + // the created contract maybe exists in statedb before the creating tx + if s := t.pre[a]; !s.exists() { + delete(t.pre, a) + } + } +} + +// GetResult returns the json-encoded nested list of call traces, and any +// error arising from the encoding or forceful termination (via `Stop`). +func (t *stateDiffTracer) GetResult() (json.RawMessage, error) { + var res []byte + var err error + if t.config.DiffMode { + res, err = json.Marshal(struct { + Post state `json:"post"` + Pre state `json:"pre"` + }{t.post, t.pre}) + } else { + res, err = json.Marshal(t.pre) + } + if err != nil { + return nil, err + } + return json.RawMessage(res), t.reason +} + +// Stop terminates execution of the tracer at the first opportune moment. +func (t *stateDiffTracer) Stop(err error) { + t.reason = err + atomic.StoreUint32(&t.interrupt, 1) +} + +// lookupAccount fetches details of an account and adds it to the prestate +// if it doesn't exist there. +func (t *stateDiffTracer) lookupAccount(addr common.Address) { + if _, ok := t.pre[addr]; ok { + return + } + + t.pre[addr] = account{ + Balance: bigToHex(t.env.StateDB.GetBalance(addr)), + Nonce: t.env.StateDB.GetNonce(addr), + storage: make(map[common.Hash]common.Hash), + } +} + +// lookupStorage fetches the requested storage slot and adds +// it to the prestate of the given contract. It assumes `lookupAccount` +// has been performed on the contract before. +func (t *stateDiffTracer) lookupStorage(addr common.Address, key common.Hash) { + if _, ok := t.pre[addr].storage[key]; ok { + return + } + t.pre[addr].storage[key] = t.env.StateDB.GetState(addr, key) +} diff --git a/eth/tracers/native/tracer.go b/eth/tracers/native/tracer.go index 3158654f3..187d89fa1 100644 --- a/eth/tracers/native/tracer.go +++ b/eth/tracers/native/tracer.go @@ -27,14 +27,17 @@ Aside from implementing the tracer, it also needs to register itself, using the Example: ```golang -func init() { - register("noopTracerNative", newNoopTracer) -} + + func init() { + register("noopTracerNative", newNoopTracer) + } + ``` */ package native import ( + "encoding/json" "errors" "github.com/ethereum/go-ethereum/eth/tracers" @@ -45,6 +48,9 @@ func init() { tracers.RegisterLookup(false, lookup) } +// ctorFn is the constructor signature of a native tracer. +type ctorFn = func(*tracers.Context, json.RawMessage) (tracers.Tracer, error) + /* ctors is a map of package-local tracer constructors. @@ -57,23 +63,23 @@ The go spec (https://golang.org/ref/spec#Package_initialization) says Hence, we cannot make the map in init, but must make it upon first use. */ -var ctors map[string]func() tracers.Tracer +var ctors map[string]ctorFn // register is used by native tracers to register their presence. -func register(name string, ctor func() tracers.Tracer) { +func register(name string, ctor ctorFn) { if ctors == nil { - ctors = make(map[string]func() tracers.Tracer) + ctors = make(map[string]ctorFn) } ctors[name] = ctor } // lookup returns a tracer, if one can be matched to the given name. -func lookup(name string, ctx *tracers.Context) (tracers.Tracer, error) { +func lookup(name string, ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, error) { if ctors == nil { - ctors = make(map[string]func() tracers.Tracer) + ctors = make(map[string]ctorFn) } if ctor, ok := ctors[name]; ok { - return ctor(), nil + return ctor(ctx, cfg) } return nil, errors.New("no tracer found") } diff --git a/eth/tracers/tracers.go b/eth/tracers/tracers.go index e8fdc08f1..710d3acd9 100644 --- a/eth/tracers/tracers.go +++ b/eth/tracers/tracers.go @@ -43,7 +43,7 @@ type Tracer interface { Stop(err error) } -type lookupFunc func(string, *Context) (Tracer, error) +type lookupFunc func(string, *Context, json.RawMessage) (Tracer, error) var ( lookups []lookupFunc @@ -63,9 +63,9 @@ func RegisterLookup(wildcard bool, lookup lookupFunc) { // New returns a new instance of a tracer, by iterating through the // registered lookups. -func New(code string, ctx *Context) (Tracer, error) { +func New(code string, ctx *Context, cfg json.RawMessage) (Tracer, error) { for _, lookup := range lookups { - if tracer, err := lookup(code, ctx); err == nil { + if tracer, err := lookup(code, ctx, cfg); err == nil { return tracer, nil } } diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index 578b10f09..421c7dafe 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -94,6 +94,16 @@ func (ec *Client) BlockNumber(ctx context.Context) (uint64, error) { return uint64(result), err } +// BlockReceipts returns the receipts of a given block number or hash. +func (ec *Client) BlockReceipts(ctx context.Context, hash common.Hash) ([]*types.Receipt, error) { + var r []*types.Receipt + err := ec.c.CallContext(ctx, &r, "eth_getBlockReceipts", hash.String()) + if err == nil && r == nil { + return nil, ethereum.NotFound + } + return r, err +} + type rpcBlock struct { Hash common.Hash `json:"hash"` Transactions []rpcTransaction `json:"transactions"` diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 1a02ec5ef..1828aa1f4 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -656,10 +656,10 @@ func (s *PublicBlockChainAPI) GetHeaderByHash(ctx context.Context, hash common.H } // GetBlockByNumber returns the requested canonical block. -// * When blockNr is -1 the chain head is returned. -// * When blockNr is -2 the pending chain head is returned. -// * When fullTx is true all transactions in the block are returned, otherwise -// only the transaction hash is returned. +// - When blockNr is -1 the chain head is returned. +// - When blockNr is -2 the pending chain head is returned. +// - When fullTx is true all transactions in the block are returned, otherwise +// only the transaction hash is returned. func (s *PublicBlockChainAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) { block, err := s.b.BlockByNumber(ctx, number) if block != nil && err == nil { @@ -816,6 +816,68 @@ func (args *CallArgs) ToMessage(globalGasCap uint64) types.Message { return msg } +// GetBlockReceipts returns the block receipts for the given block hash or number or tag. +func (api *PublicBlockChainAPI) GetBlockReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]map[string]interface{}, error) { + block, err := api.b.BlockByNumberOrHash(ctx, blockNrOrHash) + if block == nil || err != nil { + // When the block doesn't exist, the RPC method should return JSON null + // as per specification. + return nil, nil + } + receipts, err := api.b.GetReceipts(ctx, block.Hash()) + if err != nil { + return nil, err + } + txs := block.Transactions() + if len(txs) != len(receipts) { + return nil, fmt.Errorf("receipts length mismatch: %d vs %d", len(txs), len(receipts)) + } + + blockHash := block.Hash() + blockNumber := block.NumberU64() + txReceipts := make([]map[string]interface{}, 0, len(txs)) + for i, receipt := range receipts { + tx := txs[i] + var signer types.Signer = types.FrontierSigner{} + if tx.Protected() { + signer = types.NewEIP155Signer(tx.ChainId()) + } + from, _ := types.Sender(signer, tx) + + fields := map[string]interface{}{ + "blockHash": blockHash, + "blockNumber": hexutil.Uint64(blockNumber), + "transactionHash": tx.Hash(), + "transactionIndex": hexutil.Uint64(i), + "from": from, + "to": tx.To(), + "gasUsed": hexutil.Uint64(receipt.GasUsed), + "cumulativeGasUsed": hexutil.Uint64(receipt.CumulativeGasUsed), + "contractAddress": nil, + "logs": receipt.Logs, + "logsBloom": receipt.Bloom, + } + + // Assign receipt status or post state. + if len(receipt.PostState) > 0 { + fields["root"] = hexutil.Bytes(receipt.PostState) + } else { + fields["status"] = hexutil.Uint(receipt.Status) + } + if receipt.Logs == nil { + fields["logs"] = [][]*types.Log{} + } + // If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation + if receipt.ContractAddress != (common.Address{}) { + fields["contractAddress"] = receipt.ContractAddress + } + + txReceipts = append(txReceipts, fields) + } + + return txReceipts, nil +} + // OverrideAccount indicates the overriding fields of account during the execution // of a message call. // Note, state and stateDiff can't be specified at the same time. If state is diff --git a/miner/worker.go b/miner/worker.go index b9a06208b..e711c8084 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -979,6 +979,7 @@ func (w *worker) commit(uncles []*types.Header, interval func(), update bool, st } block, receipts, err := w.engine.FinalizeAndAssemble(w.chain, types.CopyHeader(w.current.header), s, w.current.txs, uncles, w.current.receipts) if err != nil { + log.Warn("Miner worker commit failed", "block number", w.current.header.Number, " error", err) return err } if w.isRunning() { diff --git a/params/config.go b/params/config.go index fd4a3e499..936eeb02c 100644 --- a/params/config.go +++ b/params/config.go @@ -51,6 +51,8 @@ var ( big.NewInt(0), big.NewInt(0), big.NewInt(0), + big.NewInt(0), + big.NewInt(0), nil, nil, nil, @@ -80,7 +82,9 @@ var ( big.NewInt(0), big.NewInt(0), big.NewInt(0), - nil, + big.NewInt(0), + big.NewInt(0), + big.NewInt(0), &CliqueConfig{Period: 0, Epoch: 30000}, nil, } @@ -104,6 +108,8 @@ var ( big.NewInt(0), big.NewInt(0), big.NewInt(0), + big.NewInt(0), + big.NewInt(0), nil, nil, nil, } @@ -171,9 +177,8 @@ type ChainConfig struct { EIP150Block *big.Int `json:"eip150Block,omitempty"` // EIP150 HF block (nil = no fork) EIP150Hash common.Hash `json:"eip150Hash,omitempty"` // EIP150 HF hash (needed for header only clients as only gas pricing changed) - EIP155Block *big.Int `json:"eip155Block,omitempty"` // EIP155 HF block - EIP158Block *big.Int `json:"eip158Block,omitempty"` // EIP158 HF block - + EIP155Block *big.Int `json:"eip155Block,omitempty"` // EIP155 HF block + EIP158Block *big.Int `json:"eip158Block,omitempty"` // EIP158 HF block ByzantiumBlock *big.Int `json:"byzantiumBlock,omitempty"` // Byzantium switch block (nil = no fork, 0 = already on byzantium) ConstantinopleBlock *big.Int `json:"constantinopleBlock,omitempty"` // Constantinople switch block (nil = no fork, 0 = already activated) PetersburgBlock *big.Int `json:"petersburgBlock,omitempty"` // Petersburg switch block (nil = same as Constantinople) @@ -188,13 +193,13 @@ type ChainConfig struct { EWASMBlock *big.Int `json:"ewasmBlock,omitempty"` // EWASM switch block (nil = no fork, 0 = already activated) RamanujanBlock *big.Int `json:"ramanujanBlock,omitempty" toml:",omitempty"` // ramanujanBlock switch block (nil = no fork, 0 = already activated) CatalystBlock *big.Int `json:"catalystBlock,omitempty"` // Catalyst switch block (nil = no fork, 0 = already on catalyst) - RamanujanBlock *big.Int `json:"ramanujanBlock,omitempty" toml:",omitempty"` // ramanujanBlock switch block (nil = no fork, 0 = already activated) - NielsBlock *big.Int `json:"nielsBlock,omitempty" toml:",omitempty"` // nielsBlock switch block (nil = no fork, 0 = already activated) - MirrorSyncBlock *big.Int `json:"mirrorSyncBlock,omitempty" toml:",omitempty"` // mirrorSyncBlock switch block (nil = no fork, 0 = already activated) - BrunoBlock *big.Int `json:"brunoBlock,omitempty" toml:",omitempty"` // brunoBlock switch block (nil = no fork, 0 = already activated) - + RamanujanBlock *big.Int `json:"ramanujanBlock,omitempty" toml:",omitempty"` // ramanujanBlock switch block (nil = no fork, 0 = already activated) + NielsBlock *big.Int `json:"nielsBlock,omitempty" toml:",omitempty"` // nielsBlock switch block (nil = no fork, 0 = already activated) + MirrorSyncBlock *big.Int `json:"mirrorSyncBlock,omitempty" toml:",omitempty"` // mirrorSyncBlock switch block (nil = no fork, 0 = already activated) + BrunoBlock *big.Int `json:"brunoBlock,omitempty" toml:",omitempty"` // brunoBlock switch block (nil = no fork, 0 = already activated) BlockRewardsBlock *big.Int `json:"blockRewardsBlock,omitempty" toml:",omitempty"` - + Contract48kBlock *big.Int `json:"contract48kBlock,omitempty" toml:",omitempty"` // contract48kBlock switch block (nil = no fork, 0 = already activated) + Fncy2Block *big.Int `json:"fncy2Block,omitempty" toml:",omitempty"` // fncy2Block switch block (nil = no fork, 0 = already activated) // Various consensus engines Clique *CliqueConfig `json:"clique,omitempty" toml:",omitempty"` Parlia *ParliaConfig `json:"parlia,omitempty" toml:",omitempty"` @@ -213,9 +218,10 @@ func (c *CliqueConfig) String() string { // ParliaConfig is the consensus engine configs for proof-of-staked-authority based sealing. type ParliaConfig struct { - Period uint64 `json:"period"` // Number of seconds between blocks to enforce - Epoch uint64 `json:"epoch"` // Epoch length to update validatorSet - BlockRewards *big.Int `json:"blockRewards"` // Block rewards to be paid for each produced block + Period uint64 `json:"period"` // Number of seconds between blocks to enforce + Epoch uint64 `json:"epoch"` // Epoch length to update validatorSet + BlockRewards *big.Int `json:"blockRewards"` // Block rewards to be paid for each produced block + StopMintBlock *big.Int `json:"stopMintBlock"` // Do not continue minting after configuring the block } // String implements the stringer interface, returning the consensus engine details. @@ -275,6 +281,13 @@ func (c *ChainConfig) IsEIP158(num *big.Int) bool { return isForked(c.EIP158Block, num) } +func (c *ChainConfig) IsContract48kBlock(num *big.Int) bool { + return isForked(c.Contract48kBlock, num) +} +func (c *ChainConfig) IsFncy2(num *big.Int) bool { + return isForked(c.Fncy2Block, num) +} + // IsByzantium returns whether num is either equal to the Byzantium fork block or greater. func (c *ChainConfig) IsByzantium(num *big.Int) bool { return isForked(c.ByzantiumBlock, num) @@ -539,12 +552,12 @@ func (err *ConfigCompatError) Error() string { // Rules is a one time interface meaning that it shouldn't be used in between transition // phases. type Rules struct { - ChainID *big.Int - IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool - IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool - IsBerlin, IsCatalyst bool - HasRuntimeUpgrade, HasDeployerProxy bool - HasBlockRewards bool + ChainID *big.Int + IsHomestead, IsEIP150, IsEIP155, IsEIP158, IsContract48kBlock bool + IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool + IsBerlin, IsCatalyst bool + HasRuntimeUpgrade, HasDeployerProxy bool + HasBlockRewards bool } // Rules ensures c's ChainID is not nil. @@ -554,19 +567,20 @@ func (c *ChainConfig) Rules(num *big.Int) Rules { chainID = new(big.Int) } return Rules{ - ChainID: new(big.Int).Set(chainID), - IsHomestead: c.IsHomestead(num), - IsEIP150: c.IsEIP150(num), - IsEIP155: c.IsEIP155(num), - IsEIP158: c.IsEIP158(num), - IsByzantium: c.IsByzantium(num), - IsConstantinople: c.IsConstantinople(num), - IsPetersburg: c.IsPetersburg(num), - IsIstanbul: c.IsIstanbul(num), - IsBerlin: c.IsBerlin(num), - IsCatalyst: c.IsCatalyst(num), - HasRuntimeUpgrade: c.HasRuntimeUpgrade(num), - HasDeployerProxy: c.HasDeployerProxy(num), - HasBlockRewards: c.IsBlockRewardsBlock(num), + ChainID: new(big.Int).Set(chainID), + IsHomestead: c.IsHomestead(num), + IsEIP150: c.IsEIP150(num), + IsEIP155: c.IsEIP155(num), + IsEIP158: c.IsEIP158(num), + IsContract48kBlock: c.IsContract48kBlock(num), + IsByzantium: c.IsByzantium(num), + IsConstantinople: c.IsConstantinople(num), + IsPetersburg: c.IsPetersburg(num), + IsIstanbul: c.IsIstanbul(num), + IsBerlin: c.IsBerlin(num), + IsCatalyst: c.IsCatalyst(num), + HasRuntimeUpgrade: c.HasRuntimeUpgrade(num), + HasDeployerProxy: c.HasDeployerProxy(num), + HasBlockRewards: c.IsBlockRewardsBlock(num), } }