Compare commits
2 commits
Author | SHA1 | Date | |
---|---|---|---|
|
feb24678b2 | ||
|
3582572c30 |
318 changed files with 2939 additions and 9745 deletions
|
@ -16,7 +16,7 @@
|
|||
"deployed": false
|
||||
},
|
||||
"lock": false,
|
||||
"isDefault": false
|
||||
"isdefault": false
|
||||
},
|
||||
{
|
||||
"address": "NVTiAjNgagDkTr5HTzDmQP9kPwPHN5BgVq",
|
||||
|
@ -41,7 +41,7 @@
|
|||
"deployed": false
|
||||
},
|
||||
"lock": false,
|
||||
"isDefault": false
|
||||
"isdefault": false
|
||||
}
|
||||
],
|
||||
"scrypt": {
|
||||
|
@ -52,4 +52,4 @@
|
|||
"extra": {
|
||||
"Tokens": null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
"deployed": false
|
||||
},
|
||||
"lock": false,
|
||||
"isDefault": false
|
||||
"isdefault": false
|
||||
},
|
||||
{
|
||||
"address": "NVTiAjNgagDkTr5HTzDmQP9kPwPHN5BgVq",
|
||||
|
@ -41,7 +41,7 @@
|
|||
"deployed": false
|
||||
},
|
||||
"lock": false,
|
||||
"isDefault": false
|
||||
"isdefault": false
|
||||
},
|
||||
{
|
||||
"address": "NfgHwwTi3wHAS8aFAN243C5vGbkYDpqLHP",
|
||||
|
@ -58,7 +58,7 @@
|
|||
"deployed": false
|
||||
},
|
||||
"lock": false,
|
||||
"isDefault": false
|
||||
"isdefault": false
|
||||
}
|
||||
],
|
||||
"scrypt": {
|
||||
|
@ -69,4 +69,4 @@
|
|||
"extra": {
|
||||
"Tokens": null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
"deployed": false
|
||||
},
|
||||
"lock": false,
|
||||
"isDefault": false
|
||||
"isdefault": false
|
||||
},
|
||||
{
|
||||
"address": "NVTiAjNgagDkTr5HTzDmQP9kPwPHN5BgVq",
|
||||
|
@ -41,7 +41,7 @@
|
|||
"deployed": false
|
||||
},
|
||||
"lock": false,
|
||||
"isDefault": false
|
||||
"isdefault": false
|
||||
}
|
||||
],
|
||||
"scrypt": {
|
||||
|
@ -52,4 +52,4 @@
|
|||
"extra": {
|
||||
"Tokens": null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
"deployed": false
|
||||
},
|
||||
"lock": false,
|
||||
"isDefault": false
|
||||
"isdefault": false
|
||||
},
|
||||
{
|
||||
"address": "NVTiAjNgagDkTr5HTzDmQP9kPwPHN5BgVq",
|
||||
|
@ -41,7 +41,7 @@
|
|||
"deployed": false
|
||||
},
|
||||
"lock": false,
|
||||
"isDefault": false
|
||||
"isdefault": false
|
||||
}
|
||||
],
|
||||
"scrypt": {
|
||||
|
@ -52,4 +52,4 @@
|
|||
"extra": {
|
||||
"Tokens": null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
"deployed": false
|
||||
},
|
||||
"lock": false,
|
||||
"isDefault": false
|
||||
"isdefault": false
|
||||
},
|
||||
{
|
||||
"address": "NVTiAjNgagDkTr5HTzDmQP9kPwPHN5BgVq",
|
||||
|
@ -41,7 +41,7 @@
|
|||
"deployed": false
|
||||
},
|
||||
"lock": false,
|
||||
"isDefault": false
|
||||
"isdefault": false
|
||||
}
|
||||
],
|
||||
"scrypt": {
|
||||
|
@ -52,4 +52,4 @@
|
|||
"extra": {
|
||||
"Tokens": null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
37
.github/workflows/build.yml
vendored
37
.github/workflows/build.yml
vendored
|
@ -37,23 +37,29 @@ jobs:
|
|||
runs-on: ${{matrix.os.name}}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [{ name: ubuntu-22.04, bin-name: linux }, { name: windows-2022, bin-name: windows }, { name: macos-12, bin-name: darwin }]
|
||||
os: [{ name: ubuntu-20.04, bin-name: linux }, { name: windows-2022, bin-name: windows }, { name: macos-12, bin-name: darwin }]
|
||||
arch: [amd64, arm64]
|
||||
exclude:
|
||||
- os: { name: windows-2022, bin-name: windows }
|
||||
arch: 'arm64'
|
||||
- os: { name: macos-12, bin-name: darwin }
|
||||
arch: 'amd64'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
# Allows to fetch all history for all branches and tags. Need this for proper versioning.
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.22'
|
||||
go-version: '1.21'
|
||||
cache: true
|
||||
|
||||
- name: Update Go modules
|
||||
run: go mod download -json
|
||||
|
||||
- name: Build CLI
|
||||
run: make build
|
||||
|
@ -64,7 +70,7 @@ jobs:
|
|||
run: mv ./bin/neo-go* ./bin/neo-go-${{ matrix.os.bin-name }}-${{ matrix.arch }}${{ (matrix.os.bin-name == 'windows' && '.exe') || '' }}
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: neo-go-${{ matrix.os.bin-name }}-${{ matrix.arch }}
|
||||
path: ./bin/neo-go*
|
||||
|
@ -79,23 +85,23 @@ jobs:
|
|||
build_image:
|
||||
needs: build_cli
|
||||
name: Build and push docker image
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Login to DockerHub
|
||||
if: ${{ github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.push_image == 'true') }}
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
|
@ -110,7 +116,7 @@ jobs:
|
|||
run: echo "latest=,${{ steps.setvars.outputs.repo }}:latest" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
push: ${{ github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.push_image == 'true') }}
|
||||
|
@ -126,20 +132,21 @@ jobs:
|
|||
runs-on: windows-2022
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
fetch-depth: 0
|
||||
|
||||
# For proper `deps` make target execution.
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.22'
|
||||
go-version: '1.21'
|
||||
cache: true
|
||||
|
||||
- name: Login to DockerHub
|
||||
if: ${{ github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.push_image == 'true') }}
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
|
|
101
.github/workflows/tests.yml
vendored
101
.github/workflows/tests.yml
vendored
|
@ -8,7 +8,7 @@ on:
|
|||
- master
|
||||
types: [opened, synchronize]
|
||||
paths-ignore:
|
||||
- 'scripts/*.sh'
|
||||
- 'scripts/**'
|
||||
- '**/*.md'
|
||||
workflow_dispatch:
|
||||
|
||||
|
@ -18,61 +18,26 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
go-version: '1.19'
|
||||
- uses: actions/checkout@v3
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v4
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
with:
|
||||
version: latest
|
||||
skip-pkg-cache: true # golangci-lint can't work with this cache enabled, ref. https://github.com/golangci/golangci-lint-action/issues/135.
|
||||
|
||||
gomodcheck:
|
||||
name: Check internal dependencies
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Check dependencies
|
||||
run: |
|
||||
./scripts/check_deps.sh
|
||||
- name: Check go.mod is tidy
|
||||
run: |
|
||||
go mod tidy
|
||||
if [[ $(git diff --name-only go.* | grep '' -c) != 0 ]]; then
|
||||
echo "go mod tidy should be executed before the merge, following packages are unused or out of date:";
|
||||
git diff go.*;
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
codegencheck:
|
||||
name: Check code generated with 'go generate' is up-to-date
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
|
||||
- name: Install stringer
|
||||
run: go install golang.org/x/tools/cmd/stringer@latest
|
||||
|
||||
- name: Run go generate
|
||||
run: go generate ./...
|
||||
|
||||
- name: Check that autogenerated code is up-to-date
|
||||
run: |
|
||||
if [[ $(git diff --name-only | grep '' -c) != 0 ]]; then
|
||||
echo "Fresh version of autogenerated code should be committed for the following files:";
|
||||
git diff --name-only;
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
codeql:
|
||||
name: CodeQL
|
||||
|
@ -88,11 +53,11 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
|
@ -103,7 +68,7 @@ jobs:
|
|||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
@ -117,37 +82,37 @@ jobs:
|
|||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
uses: github/codeql-action/analyze@v2
|
||||
|
||||
test_cover:
|
||||
name: Coverage
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
env:
|
||||
CGO_ENABLED: 0
|
||||
GOEXPERIMENT: nocoverageredesign
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: 'true'
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.22'
|
||||
go-version: '1.21'
|
||||
cache: true
|
||||
|
||||
- name: Update Go modules
|
||||
run: go mod download -json
|
||||
|
||||
- name: Write coverage profile
|
||||
run: go test -timeout 15m -v ./... -coverprofile=./coverage.txt -covermode=atomic -coverpkg=./pkg...,./cli/...
|
||||
run: go test -v ./... -coverprofile=./coverage.txt -covermode=atomic -coverpkg=./pkg...,./cli/...
|
||||
|
||||
- name: Upload coverage results to Codecov
|
||||
uses: codecov/codecov-action@v4
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
fail_ci_if_error: true # if something is wrong on uploading codecov results, then this job will fail
|
||||
files: ./coverage.txt
|
||||
slug: nspcc-dev/neo-go
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
verbose: true
|
||||
|
||||
tests:
|
||||
|
@ -155,36 +120,36 @@ jobs:
|
|||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-22.04, windows-2022, macos-12, macos-14]
|
||||
go_versions: [ '1.20', '1.21', '1.22' ]
|
||||
os: [ubuntu-20.04, windows-2022, macos-12]
|
||||
go_versions: [ '1.19', '1.20', '1.21' ]
|
||||
exclude:
|
||||
# Only latest Go version for Windows and MacOS.
|
||||
- os: windows-2022
|
||||
go_versions: '1.20'
|
||||
go_versions: '1.19'
|
||||
- os: windows-2022
|
||||
go_versions: '1.21'
|
||||
- os: macos-12
|
||||
go_versions: '1.20'
|
||||
- os: macos-12
|
||||
go_versions: '1.21'
|
||||
- os: macos-14
|
||||
go_versions: '1.19'
|
||||
- os: macos-12
|
||||
go_versions: '1.20'
|
||||
- os: macos-14
|
||||
go_versions: '1.21'
|
||||
# Exclude latest Go version for Ubuntu as Coverage uses it.
|
||||
- os: ubuntu-22.04
|
||||
go_versions: '1.22'
|
||||
- os: ubuntu-20.04
|
||||
go_versions: '1.21'
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: 'true'
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '${{ matrix.go_versions }}'
|
||||
cache: true
|
||||
|
||||
- name: Update Go modules
|
||||
run: go mod download -json
|
||||
|
||||
- name: Run tests
|
||||
run: go test -timeout 15m -v -race ./...
|
||||
run: go test -v -race ./...
|
||||
|
|
184
CHANGELOG.md
184
CHANGELOG.md
|
@ -2,188 +2,6 @@
|
|||
|
||||
This document outlines major changes between releases.
|
||||
|
||||
## 0.106.1 "Implication" (3 Jun 2024)
|
||||
|
||||
An urgent release that fixes mainnet state difference at block 5462944 which halts
|
||||
blocks processing starting from the height 5468658. This release requires full node
|
||||
DB resynchronization for mainnet nodes. T5 testnet DB state is not affected by this
|
||||
bug (at least up to the current 4087361 height). Thus, DB resynchronisation may be
|
||||
skipped for testnet nodes. No configuration changes implied.
|
||||
|
||||
Bugs fixed:
|
||||
* mainnet state difference at block 5462944 caused by runtime notification
|
||||
permissions check against the updated contract state instead of executing state
|
||||
(#3472)
|
||||
* unused neofs-contract dependency in the node modules (#3458)
|
||||
|
||||
## 0.106.0 "Zephyranthes" (21 May 2024)
|
||||
|
||||
We're rolling out a large set of updates including all of Neo 3.7.4 protocol changes:
|
||||
native contracts update functionality and extended native contract APIs united under
|
||||
the upcoming Cockatrice hardfork. For smart contract developers an ability to
|
||||
generate smart contract bindings with dynamic hash is supported as well as a number
|
||||
of useful extensions for `unwrap` package, compatible NNS smart contract RPC binding
|
||||
and a lot of other handy enhancements. This release also includes a couple of severe
|
||||
regression bug fixes affecting the node state. As a bonus of fixing a wide range of
|
||||
failing tests, we've refactored the node services start and shutdown procedures to
|
||||
make it more stable. This version drops support for Go 1.19 and requires 1.20+ to
|
||||
build (with Go 1.22 supported).
|
||||
|
||||
Notice that this release requires full node resynchronization for both mainnet
|
||||
and testnet nodes. Please pay a special attention to the Cockatrice hardfork schedule
|
||||
and check your configurations. It should be configured for 3967000 of T5 testnet and
|
||||
5450000 of mainnet. To ensure compatibility your node must be configured
|
||||
appropriately.
|
||||
|
||||
New features:
|
||||
* native contracts update functionality bound to hardforks (#3402, #3444)
|
||||
* Cockatrice hardfork planned for 5450000 block of mainnet and 3967000 block of T5
|
||||
testnet (#3402, #3448, #3402, #3446)
|
||||
* `CommitteeChanged` events are emitted by NeoToken native contract starting from
|
||||
Cockatrice hardfork (#3351, #3448)
|
||||
* `getCommitteeAddress` method of NeoToken native contract is available starting
|
||||
from Cockatrice hardfork (#3362, #3402)
|
||||
* `keccak256` method of CryptoLib native contract is available starting from
|
||||
Cockatrice hardfork (#3301, #3402)
|
||||
* dynamic contract hash support for smart contract bindings (#3405)
|
||||
* support `StringCompressed` API for `crypto.PublicKey` (#3408)
|
||||
* support `Copy` API for `transaction.Transaction` and `payload.P2PNotaryRequest`
|
||||
(#3407)
|
||||
* extend `verifyWithECDsa` method of native CryptoLib contract with Keccak256 hasher
|
||||
starting from Cockatrice and add an example of custom Koblitz-based and
|
||||
Keccak256-based transaction witness verification (#3425)
|
||||
* autogenerated `nativehashes` package (#3402, #3431)
|
||||
* introduce `unwrap.Exception` type for better RPC invocation result exceptions
|
||||
detection (#3438)
|
||||
|
||||
Behavior changes:
|
||||
* Neo Name Service smart contract RPC binding follows the official N3 implementation
|
||||
(#3291)
|
||||
* clear LastGasPerVote NeoToken account info on unvoting (#3349)
|
||||
* return fault exception (if any) in `unwrap` RPC client helpers (#3356)
|
||||
* move P2PNotary designation role out of P2PSigExtensions (#3452)
|
||||
|
||||
Improvements:
|
||||
* support `smartcontract.Convertible` interface as RPC Actor and Invoker call
|
||||
parameters (#3297)
|
||||
* allow to import multisignature account into wallet without WIF and password
|
||||
specified (#3293)
|
||||
* upgrade go-ordered-json dependency to avoid possible node state incompatibility
|
||||
issues caused by smart contract manifest marshalling (#3331, #3333)
|
||||
* Go 1.22 support, bump minimum required Go version up to Go 1.20 (#3336)
|
||||
* a number of dependent libraries are updated to the fresh versions (#3338, #3418)
|
||||
* improve error message of `System.Crypto.CheckMultisig` interop API handler (#3374)
|
||||
* upgrade dBFT library to v0.2.0 (#3371, #3413)
|
||||
* increase `ValidUntilBlock` value for transactions generated by CLI commands
|
||||
(#3376)
|
||||
* documentation updates (#3375, #3382)
|
||||
* let default Notary Actor options be customizable (#3394)
|
||||
* extend `getversion` RPC response with RPC server settings (#3386)
|
||||
* make errors related to wallet opening more detailed (#3389)
|
||||
* adjust error messages of `setExecFeeFactor` and `setStoragePrice` methods of
|
||||
native PolicyContract (#3406)
|
||||
* make neotest chain constructor options customizable (#3404)
|
||||
* format improvements for CLI commands description (#3410)
|
||||
* make state dumps comparator script more verbose (#3411)
|
||||
* refactor storage `Get` implementation for BoltDB (#3441)
|
||||
* add `updatecounter` field to the resulting items of `getnativecontracts` RPC API
|
||||
call (#3439)
|
||||
|
||||
Bugs fixed:
|
||||
* node panic on committee missing from node configuration (#3294)
|
||||
* autogenerated RPC bindings do not follow Go naming convention (#3299)
|
||||
* a batch of failing tests is fixed (#3306, #3313, #3321, #3332, #3337, #3335,
|
||||
#3344, #3340, #3350, #3355, #3364, #3368, #3377, #3393, #3397, #3392, #3398,
|
||||
#3400)
|
||||
* outdated minimum required Go version of boilerplate contract generated by
|
||||
`neo-go contract init` (#3318)
|
||||
* outdated address used as an example in RPC client documentation (#3327)
|
||||
* ungraceful node services shutdown procedure (#3307)
|
||||
* logging data race on node services shutdown (#3307)
|
||||
* Map parameter support is missing from RPC server handlers (#3329)
|
||||
* smart contract storage iterator prefix wasn't copied while iterating over values
|
||||
(#3336)
|
||||
* RPC error with -511 code (insufficient funds) returned on `sendrawtransaction` RPC
|
||||
request should cover multiple cases of sender's insufficient funds (#3360, #3361)
|
||||
* reentrancy possibility for Notary deposit withdrawal (#3357)
|
||||
* null `findstorage` RPC response in case of missing storage items (#3385)
|
||||
* uninitialized named return variables in compiler (#3401)
|
||||
* wrong debug sequence points after `JUMP*` instructions shortening by compiler
|
||||
(#3412)
|
||||
* corrupted genesis block record and application log caused by improper Conflicts
|
||||
attribute processing (#3437)
|
||||
* false positive DB-based blocked accounts detection in native PolicyContract leaded
|
||||
to invalid committee computations and reward distribution made by NeoToken (#3443)
|
||||
|
||||
## 0.105.1 "Enumeration" (12 Jan 2024)
|
||||
|
||||
This is another v3.6.2-compatible release that fixes mainnet state difference at
|
||||
block 4688591. It is confirmed to have the same state up to 4723K height (which
|
||||
is current), but to get proper mainnet state you need to resynchronize your node
|
||||
from the genesis. T5 testnet state is not affected (at least up to the current
|
||||
3323K height), thus DB resynchronisation may be skipped for testnet nodes.
|
||||
|
||||
Improvements:
|
||||
* better network services logging (#3287, #3290)
|
||||
|
||||
Bugs fixed:
|
||||
* state difference at block 4688591 of N3 mainnet caused by difference at
|
||||
characters escaping during manifest's `Extra` field JSON serialisation (#3286)
|
||||
|
||||
## 0.105.0 "Designation" (29 Dec 2023)
|
||||
|
||||
We're rolling out an update for NeoGo nodes that contains a number of user-facing
|
||||
API improvements for RPC web-socket notification subsystem, CLI utility, wallet
|
||||
related packages and not only. Try out our new `--await` CLI option for those
|
||||
commands that relay transactions to the network to automatically wait for the
|
||||
on-chain transaction execution result. Subscribe for new block headers with
|
||||
extended RPC notification subsystem interface. Use contract-based accounts
|
||||
provided by `wallet` package and `neotest` framework to sign transactions. These
|
||||
and a set of other improvements are available to our users while this release is
|
||||
staying compatible with 3.6.2 version of C# node.
|
||||
|
||||
This version also delivers a bug fix for consensus node panic caused by improper
|
||||
native NeoToken cache initialisation. Moreover, there's a set of RPC server side
|
||||
improvements, thus, we recommend to upgrade both consensus and RPC nodes to
|
||||
provide more stable consensus node functioning and extended user APIs functionality.
|
||||
No database resynchronisation is needed.
|
||||
|
||||
New features:
|
||||
* block headers RPC web-socket subscription (#3252)
|
||||
* --await option to synchronize on transaction execution for CLI commands (#3265)
|
||||
* partial session-based RPC iterator unwrapping (#3274)
|
||||
* contract-based transaction signers in neotest framework (#3233)
|
||||
* AMD64 release binaries for macOS (#3251)
|
||||
* complex contract signature schemes in wallet.Account (#3256)
|
||||
|
||||
Behavior changes:
|
||||
* basic RPC subscription filter validity checks are implemented on both RPC
|
||||
client and RPC server sides (#3258)
|
||||
* filter of notary request event RPC subscription is extended with `type` field
|
||||
(#3236)
|
||||
* if available, use block headers RPC web-socket subscription for transaction
|
||||
awaiting via `waiter` package API (#3283)
|
||||
|
||||
Improvements:
|
||||
* add smart contract storage limits to interop utilities (#3232)
|
||||
* extend ZKP examples documentation with additional links to PoT ceremony
|
||||
response files (#3234)
|
||||
* support Go types in VM emitter API (#3237)
|
||||
* documentation update (#3239, #3242, #3246)
|
||||
* BoltDB (go.etcd.io/bbolt) dependency upgrade (#3250)
|
||||
* CLI code refactoring (#2682)
|
||||
* extend wallet package to work with byte slice based wallets (#3255)
|
||||
* export RPC client side transaction awaiting functionality via `waiter` package
|
||||
(#3265, #3283)
|
||||
|
||||
Bugs fixed:
|
||||
* remove stale `updatehistory` section of `getnativecontracts` RPC response (#3240)
|
||||
* immediately check RPC client initialisation on access to blocks RPC subscription
|
||||
API (#3257, #3261)
|
||||
* fix CN panic caused by unexpected call to native NeoToken cache (#3253)
|
||||
* make "automatically generated" warning of all automatically generated files
|
||||
follow the standard (#3280)
|
||||
|
||||
## 0.104.0 "Globalization" (27 Nov 2023)
|
||||
|
||||
We're updating NeoGo to push out a number of useful updates and protocol
|
||||
|
@ -2609,7 +2427,7 @@ Behavior changes:
|
|||
* contracts no longer have single entry point, rather they export a set of
|
||||
methods with specific offsets. Go smart contract compiler has been changed
|
||||
accordingly to add all exported (as in Go) methods to the manifest
|
||||
(but with the first letter being lowercased to match NEP-5 expectations,
|
||||
(but with the first letter being lowercased to match NEP-5 expections,
|
||||
#1228). Please also refer to examples changes to better see how it affects
|
||||
contracts, manifests and configuration files (#1296)
|
||||
* native contracts are now called via Neo.Native.Call syscall (#1191)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Builder image
|
||||
# Keep go version in sync with Build GA job.
|
||||
FROM golang:1.22-alpine as builder
|
||||
FROM golang:1.21-alpine as builder
|
||||
|
||||
# Display go version for information purposes.
|
||||
RUN go version
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Builder image
|
||||
# Keep go version in sync with Build GA job.
|
||||
FROM golang:1.22.0-windowsservercore-ltsc2022 as builder
|
||||
FROM golang:1.21.3-windowsservercore-ltsc2022 as builder
|
||||
|
||||
COPY . /neo-go
|
||||
|
||||
|
|
2
Makefile
2
Makefile
|
@ -3,7 +3,7 @@ REPONAME = "neo-go"
|
|||
NETMODE ?= "privnet"
|
||||
BINARY=neo-go
|
||||
BINARY_PATH=./bin/$(BINARY)$(shell go env GOEXE)
|
||||
GO_VERSION ?= 1.20
|
||||
GO_VERSION ?= 1.19
|
||||
DESTDIR = ""
|
||||
SYSCONFIGDIR = "/etc"
|
||||
BINDIR = "/usr/bin"
|
||||
|
|
|
@ -51,7 +51,7 @@ NeoGo, `:latest` points to the latest release) or build yourself.
|
|||
|
||||
### Building
|
||||
|
||||
Building NeoGo requires Go 1.20+ and `make`:
|
||||
Building NeoGo requires Go 1.19+ and `make`:
|
||||
|
||||
```
|
||||
make
|
||||
|
|
33
ROADMAP.md
33
ROADMAP.md
|
@ -7,13 +7,14 @@ functionality.
|
|||
## Versions 0.7X.Y (as needed)
|
||||
* Neo 2.0 support (bug fixes, minor functionality additions)
|
||||
|
||||
## Version 0.107.0 (~Jun-Jul 2024)
|
||||
* protocol updates
|
||||
## Version 0.102.1 (~October 2023)
|
||||
* bug fixes
|
||||
* node resynchronisation from local DB
|
||||
* CLI library upgrade
|
||||
|
||||
## Version 1.0 (2024, TBD)
|
||||
## Version 0.103.0 (~November 2023)
|
||||
* extended data types for iterators to be used by RPC wrapper generator
|
||||
* RPC subscription extensions
|
||||
|
||||
## Version 1.0 (2023, TBD)
|
||||
* stable version
|
||||
|
||||
# Deprecated functionality
|
||||
|
@ -31,15 +32,15 @@ GetPeers RPC command returns a list of Peers where the port type has changed fro
|
|||
string to uint16 to match C#. The RPC client currently supports unmarshalling both
|
||||
formats.
|
||||
|
||||
Removal of Peer unmarshalling with string based ports is scheduled for Jun-Jul 2024
|
||||
(~0.107.0 release).
|
||||
Removal of Peer unmarshalling with string based ports is scheduled for ~September 2023
|
||||
(~0.105.0 release).
|
||||
|
||||
## `NEOBalance` from stack item
|
||||
|
||||
We check struct items count before convert LastGasPerVote to let RPC client be compatible with
|
||||
old versions.
|
||||
|
||||
Removal of this compatiblility code is scheduled for Jun-Jul 2024.
|
||||
Removal of this compatiblility code is scheduled for Sep-Oct 2023.
|
||||
|
||||
## `serv_node_version` Prometheus gauge metric
|
||||
|
||||
|
@ -48,7 +49,7 @@ metrics with proper version formatting. `neogo_version` contains NeoGo version
|
|||
hidden under `version` label and `server_id` contains network server ID hidden
|
||||
under `server_id` label.
|
||||
|
||||
Removal of `serv_node_version` is scheduled for Jun-Jul 2024 (~0.107.0 release).
|
||||
Removal of `serv_node_version` is scheduled for Sep-Oct 2023 (~0.105.0 release).
|
||||
|
||||
## RPC error codes returned by old versions and C#-nodes
|
||||
|
||||
|
@ -56,16 +57,4 @@ NeoGo retains certain deprecated error codes: `neorpc.ErrCompatGeneric`,
|
|||
`neorpc.ErrCompatNoOpenedWallet`. They returned by nodes not compliant with the
|
||||
neo-project/proposals#156 (NeoGo pre-0.102.0 and all known C# versions).
|
||||
|
||||
Removal of the deprecated RPC error codes is planned for Jun-Jul 2024 (~0.107.0
|
||||
release).
|
||||
|
||||
## Block based web-socket waiter transaction awaiting
|
||||
|
||||
Web-socket RPC based `waiter.EventWaiter` uses `header_of_added_block` notifications
|
||||
subscription to manage transaction awaiting. To support old NeoGo RPC servers
|
||||
(older than 0.105.0) that do not have block headers subscription ability,
|
||||
event-based waiter fallbacks to the old way of block monitoring with
|
||||
`block_added` notifications subscription.
|
||||
|
||||
Removal of stale RPC server compatibility code from `waiter.EventWaiter` is
|
||||
scheduled for Jun-Jul 2024 (~0.107.0 release).
|
||||
Removal of the deprecated RPC error codes is planned once all nodes adopt the new error standard.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package cmdargs
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
|
@ -44,7 +45,7 @@ func TestParseCosigner(t *testing.T) {
|
|||
Scopes: transaction.CalledByEntry | transaction.CustomContracts,
|
||||
AllowedContracts: []util.Uint160{c1, c2},
|
||||
},
|
||||
acc.StringLE() + ":CustomGroups:" + priv.PublicKey().StringCompressed(): {
|
||||
acc.StringLE() + ":CustomGroups:" + hex.EncodeToString(priv.PublicKey().Bytes()): {
|
||||
Account: acc,
|
||||
Scopes: transaction.CustomGroups,
|
||||
AllowedGroups: keys.PublicKeys{priv.PublicKey()},
|
||||
|
|
|
@ -328,14 +328,6 @@ func TestNEP11_ND_OwnerOf_BalanceOf_Transfer(t *testing.T) {
|
|||
e.Run(t, append(cmdCheckBalance, "--token", h.StringLE())...)
|
||||
checkBalanceResult(t, nftOwnerAddr, tokenID1)
|
||||
|
||||
// check --await flag
|
||||
tokenID2 := mint(t)
|
||||
e.In.WriteString(nftOwnerPass + "\r")
|
||||
e.Run(t, append(cmdTransfer, "--await", "--id", hex.EncodeToString(tokenID2))...)
|
||||
e.CheckAwaitableTxPersisted(t)
|
||||
e.Run(t, append(cmdCheckBalance, "--token", h.StringLE())...)
|
||||
checkBalanceResult(t, nftOwnerAddr, tokenID1)
|
||||
|
||||
// transfer: good, to NEP-11-Payable contract, with data
|
||||
verifyH := deployVerifyContract(t, e)
|
||||
cmdTransfer = []string{
|
||||
|
|
|
@ -19,34 +19,19 @@ import (
|
|||
|
||||
func TestNEP17Balance(t *testing.T) {
|
||||
e := testcli.NewExecutor(t, true)
|
||||
|
||||
args := []string{
|
||||
"neo-go", "wallet", "nep17", "multitransfer",
|
||||
"--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
|
||||
"--wallet", testcli.ValidatorWallet,
|
||||
"--from", testcli.ValidatorAddr,
|
||||
"GAS:" + testcli.TestWalletMultiAccount1 + ":1",
|
||||
"NEO:" + testcli.TestWalletMultiAccount1 + ":10",
|
||||
"GAS:" + testcli.TestWalletMultiAccount3 + ":3",
|
||||
"--force",
|
||||
}
|
||||
e.In.WriteString("one\r")
|
||||
e.Run(t, args...)
|
||||
e.CheckTxPersisted(t)
|
||||
|
||||
cmdbalance := []string{"neo-go", "wallet", "nep17", "balance"}
|
||||
cmdbase := append(cmdbalance,
|
||||
"--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
|
||||
"--wallet", testcli.TestWalletMultiPath,
|
||||
"--wallet", testcli.ValidatorWallet,
|
||||
)
|
||||
cmd := append(cmdbase, "--address", testcli.TestWalletMultiAccount1)
|
||||
cmd := append(cmdbase, "--address", testcli.ValidatorAddr)
|
||||
t.Run("excessive parameters", func(t *testing.T) {
|
||||
e.RunWithError(t, append(cmd, "--token", "NEO", "gas")...)
|
||||
})
|
||||
t.Run("NEO", func(t *testing.T) {
|
||||
b, index := e.Chain.GetGoverningTokenBalance(testcli.TestWalletMultiAccount1Hash)
|
||||
b, index := e.Chain.GetGoverningTokenBalance(testcli.ValidatorHash)
|
||||
checkResult := func(t *testing.T) {
|
||||
e.CheckNextLine(t, "^\\s*Account\\s+"+testcli.TestWalletMultiAccount1)
|
||||
e.CheckNextLine(t, "^\\s*Account\\s+"+testcli.ValidatorAddr)
|
||||
e.CheckNextLine(t, "^\\s*NEO:\\s+NeoToken \\("+e.Chain.GoverningTokenHash().StringLE()+"\\)")
|
||||
e.CheckNextLine(t, "^\\s*Amount\\s*:\\s*"+b.String()+"$")
|
||||
e.CheckNextLine(t, "^\\s*Updated\\s*:\\s*"+strconv.FormatUint(uint64(index), 10))
|
||||
|
@ -63,53 +48,65 @@ func TestNEP17Balance(t *testing.T) {
|
|||
})
|
||||
t.Run("GAS", func(t *testing.T) {
|
||||
e.Run(t, append(cmd, "--token", "GAS")...)
|
||||
e.CheckNextLine(t, "^\\s*Account\\s+"+testcli.TestWalletMultiAccount1)
|
||||
e.CheckNextLine(t, "^\\s*Account\\s+"+testcli.ValidatorAddr)
|
||||
e.CheckNextLine(t, "^\\s*GAS:\\s+GasToken \\("+e.Chain.UtilityTokenHash().StringLE()+"\\)")
|
||||
b := e.Chain.GetUtilityTokenBalance(testcli.TestWalletMultiAccount1Hash)
|
||||
b := e.Chain.GetUtilityTokenBalance(testcli.ValidatorHash)
|
||||
e.CheckNextLine(t, "^\\s*Amount\\s*:\\s*"+fixedn.Fixed8(b.Int64()).String()+"$")
|
||||
})
|
||||
t.Run("zero balance of known token", func(t *testing.T) {
|
||||
e.Run(t, append(cmdbase, []string{"--token", "NEO", "--address", testcli.TestWalletMultiAccount2}...)...)
|
||||
e.CheckNextLine(t, "^Account "+testcli.TestWalletMultiAccount2)
|
||||
e.Run(t, append(cmdbase, []string{"--token", "NEO"}...)...)
|
||||
addr1, err := address.StringToUint160("Nhfg3TbpwogLvDGVvAvqyThbsHgoSUKwtn")
|
||||
require.NoError(t, err)
|
||||
e.CheckNextLine(t, "^Account "+address.Uint160ToString(addr1))
|
||||
e.CheckNextLine(t, "^\\s*NEO:\\s+NeoToken \\("+e.Chain.GoverningTokenHash().StringLE()+"\\)")
|
||||
e.CheckNextLine(t, "^\\s*Amount\\s*:\\s*"+fixedn.Fixed8(0).String()+"$")
|
||||
e.CheckNextLine(t, "^\\s*Updated:")
|
||||
e.CheckEOF(t)
|
||||
e.CheckNextLine(t, "^\\s*$")
|
||||
})
|
||||
t.Run("all accounts", func(t *testing.T) {
|
||||
e.Run(t, cmdbase...)
|
||||
addr1, err := address.StringToUint160("Nhfg3TbpwogLvDGVvAvqyThbsHgoSUKwtn")
|
||||
require.NoError(t, err)
|
||||
e.CheckNextLine(t, "^Account "+address.Uint160ToString(addr1))
|
||||
e.CheckNextLine(t, "^\\s*GAS:\\s+GasToken \\("+e.Chain.UtilityTokenHash().StringLE()+"\\)")
|
||||
balance := e.Chain.GetUtilityTokenBalance(addr1)
|
||||
e.CheckNextLine(t, "^\\s*Amount\\s*:\\s*"+fixedn.Fixed8(balance.Int64()).String()+"$")
|
||||
e.CheckNextLine(t, "^\\s*Updated:")
|
||||
e.CheckNextLine(t, "^\\s*$")
|
||||
|
||||
e.CheckNextLine(t, "^Account "+testcli.TestWalletMultiAccount1)
|
||||
addr2, err := address.StringToUint160("NVTiAjNgagDkTr5HTzDmQP9kPwPHN5BgVq")
|
||||
require.NoError(t, err)
|
||||
e.CheckNextLine(t, "^Account "+address.Uint160ToString(addr2))
|
||||
e.CheckNextLine(t, "^\\s*$")
|
||||
|
||||
addr3, err := address.StringToUint160("NfgHwwTi3wHAS8aFAN243C5vGbkYDpqLHP")
|
||||
require.NoError(t, err)
|
||||
e.CheckNextLine(t, "^Account "+address.Uint160ToString(addr3))
|
||||
// The order of assets is undefined.
|
||||
for i := 0; i < 2; i++ {
|
||||
line := e.GetNextLine(t)
|
||||
if strings.Contains(line, "GAS") {
|
||||
e.CheckLine(t, line, "^\\s*GAS:\\s+GasToken \\("+e.Chain.UtilityTokenHash().StringLE()+"\\)")
|
||||
balance := e.Chain.GetUtilityTokenBalance(testcli.TestWalletMultiAccount1Hash)
|
||||
balance = e.Chain.GetUtilityTokenBalance(addr3)
|
||||
e.CheckNextLine(t, "^\\s*Amount\\s*:\\s*"+fixedn.Fixed8(balance.Int64()).String()+"$")
|
||||
e.CheckNextLine(t, "^\\s*Updated:")
|
||||
} else {
|
||||
balance, index := e.Chain.GetGoverningTokenBalance(testcli.TestWalletMultiAccount1Hash)
|
||||
balance, index := e.Chain.GetGoverningTokenBalance(testcli.ValidatorHash)
|
||||
e.CheckLine(t, line, "^\\s*NEO:\\s+NeoToken \\("+e.Chain.GoverningTokenHash().StringLE()+"\\)")
|
||||
e.CheckNextLine(t, "^\\s*Amount\\s*:\\s*"+balance.String()+"$")
|
||||
e.CheckNextLine(t, "^\\s*Updated\\s*:\\s*"+strconv.FormatUint(uint64(index), 10))
|
||||
}
|
||||
}
|
||||
e.CheckNextLine(t, "^\\s*$")
|
||||
|
||||
e.CheckNextLine(t, "^Account "+testcli.TestWalletMultiAccount2)
|
||||
e.CheckNextLine(t, "^\\s*$")
|
||||
|
||||
e.CheckNextLine(t, "^Account "+testcli.TestWalletMultiAccount3)
|
||||
e.CheckNextLine(t, "^\\s*GAS:\\s+GasToken \\("+e.Chain.UtilityTokenHash().StringLE()+"\\)")
|
||||
balance := e.Chain.GetUtilityTokenBalance(testcli.TestWalletMultiAccount3Hash)
|
||||
e.CheckNextLine(t, "^\\s*Amount\\s*:\\s*"+fixedn.Fixed8(balance.Int64()).String()+"$")
|
||||
e.CheckNextLine(t, "^\\s*Updated:")
|
||||
addr4, err := address.StringToUint160("NiFxRcC5Anz9pmqQyMHh5vamBUZDbRRRzA") // deployed verify.go contract
|
||||
require.NoError(t, err)
|
||||
e.CheckNextLine(t, "^Account "+address.Uint160ToString(addr4))
|
||||
e.CheckEOF(t)
|
||||
})
|
||||
t.Run("Bad token", func(t *testing.T) {
|
||||
e.Run(t, append(cmd, "--token", "kek")...)
|
||||
e.CheckNextLine(t, "^\\s*Account\\s+"+testcli.TestWalletMultiAccount1)
|
||||
e.CheckNextLine(t, "^\\s*Account\\s+"+testcli.ValidatorAddr)
|
||||
e.CheckNextLine(t, `^\s*Can't find data for "kek" token\s*`)
|
||||
e.CheckEOF(t)
|
||||
})
|
||||
|
@ -226,19 +223,12 @@ func TestNEP17Transfer(t *testing.T) {
|
|||
"neo-go", "wallet", "nep17", "transfer",
|
||||
"--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
|
||||
"--wallet", testcli.ValidatorWallet,
|
||||
"--to", address.Uint160ToString(e.Chain.GetNotaryContractScriptHash()),
|
||||
"--token", "GAS",
|
||||
"--amount", "1",
|
||||
"--from", testcli.ValidatorAddr,
|
||||
"--force",
|
||||
"--from", testcli.ValidatorAddr}
|
||||
|
||||
t.Run("with await", func(t *testing.T) {
|
||||
e.In.WriteString("one\r")
|
||||
e.Run(t, append(cmd, "--to", nftOwnerAddr, "--await")...)
|
||||
e.CheckAwaitableTxPersisted(t)
|
||||
})
|
||||
|
||||
cmd = append(cmd, "--to", address.Uint160ToString(e.Chain.GetNotaryContractScriptHash()),
|
||||
"[", testcli.ValidatorAddr, strconv.Itoa(int(validTil)), "]")
|
||||
"[", testcli.ValidatorAddr, strconv.Itoa(int(validTil)), "]"}
|
||||
|
||||
t.Run("with data", func(t *testing.T) {
|
||||
e.In.WriteString("one\r")
|
||||
|
|
|
@ -11,36 +11,22 @@ import (
|
|||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/cli/flags"
|
||||
"github.com/nspcc-dev/neo-go/cli/input"
|
||||
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
"github.com/urfave/cli"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"golang.org/x/term"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultTimeout is the default timeout used for RPC requests.
|
||||
DefaultTimeout = 10 * time.Second
|
||||
// DefaultAwaitableTimeout is the default timeout used for RPC requests that
|
||||
// require transaction awaiting. It is set to the approximate time of three
|
||||
// Neo N3 mainnet blocks accepting.
|
||||
DefaultAwaitableTimeout = 3 * 15 * time.Second
|
||||
)
|
||||
// DefaultTimeout is the default timeout used for RPC requests.
|
||||
const DefaultTimeout = 10 * time.Second
|
||||
|
||||
// RPCEndpointFlag is a long flag name for an RPC endpoint. It can be used to
|
||||
// check for flag presence in the context.
|
||||
|
@ -111,8 +97,6 @@ var Debug = cli.BoolFlag{
|
|||
|
||||
var errNoEndpoint = errors.New("no RPC endpoint specified, use option '--" + RPCEndpointFlag + "' or '-r'")
|
||||
var errInvalidHistoric = errors.New("invalid 'historic' parameter, neither a block number, nor a block/state hash")
|
||||
var errNoWallet = errors.New("no wallet parameter found, specify it with the '--wallet' or '-w' flag or specify wallet config file with the '--wallet-config' flag")
|
||||
var errConflictingWalletFlags = errors.New("--wallet flag conflicts with --wallet-config flag, please, provide one of them to specify wallet location")
|
||||
|
||||
// GetNetwork examines Context's flags and returns the appropriate network. It
|
||||
// defaults to PrivNet if no flags are given.
|
||||
|
@ -136,9 +120,6 @@ func GetTimeoutContext(ctx *cli.Context) (context.Context, func()) {
|
|||
if dur == 0 {
|
||||
dur = DefaultTimeout
|
||||
}
|
||||
if !ctx.IsSet("timeout") && ctx.Bool("await") {
|
||||
dur = DefaultAwaitableTimeout
|
||||
}
|
||||
return context.WithTimeout(context.Background(), dur)
|
||||
}
|
||||
|
||||
|
@ -220,7 +201,6 @@ var (
|
|||
// If logPath is configured -- function creates a dir and a file for logging.
|
||||
// If logPath is configured on Windows -- function returns closer to be
|
||||
// able to close sink for the opened log output file.
|
||||
// If the program is run in TTY then logger adds timestamp to its entries.
|
||||
func HandleLoggingParams(debug bool, cfg config.ApplicationConfiguration) (*zap.Logger, *zap.AtomicLevel, func() error, error) {
|
||||
var (
|
||||
level = zapcore.InfoLevel
|
||||
|
@ -241,11 +221,7 @@ func HandleLoggingParams(debug bool, cfg config.ApplicationConfiguration) (*zap.
|
|||
cc.DisableStacktrace = true
|
||||
cc.EncoderConfig.EncodeDuration = zapcore.StringDurationEncoder
|
||||
cc.EncoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
|
||||
if term.IsTerminal(int(os.Stdout.Fd())) {
|
||||
cc.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
|
||||
} else {
|
||||
cc.EncoderConfig.EncodeTime = func(t time.Time, encoder zapcore.PrimitiveArrayEncoder) {}
|
||||
}
|
||||
cc.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
|
||||
cc.Encoding = "console"
|
||||
cc.Level = zap.NewAtomicLevelAt(level)
|
||||
cc.Sampling = nil
|
||||
|
@ -303,108 +279,3 @@ func HandleLoggingParams(debug bool, cfg config.ApplicationConfiguration) (*zap.
|
|||
log, err := cc.Build()
|
||||
return log, &cc.Level, _winfileSinkCloser, err
|
||||
}
|
||||
|
||||
// GetRPCWithActor returns an RPC client instance and Actor instance for the given context.
|
||||
func GetRPCWithActor(gctx context.Context, ctx *cli.Context, signers []actor.SignerAccount) (*rpcclient.Client, *actor.Actor, cli.ExitCoder) {
|
||||
c, err := GetRPCClient(gctx, ctx)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
a, actorErr := actor.New(c, signers)
|
||||
if actorErr != nil {
|
||||
c.Close()
|
||||
return nil, nil, cli.NewExitError(fmt.Errorf("failed to create Actor: %w", actorErr), 1)
|
||||
}
|
||||
return c, a, nil
|
||||
}
|
||||
|
||||
// GetAccFromContext returns account and wallet from context. If address is not set, default address is used.
|
||||
func GetAccFromContext(ctx *cli.Context) (*wallet.Account, *wallet.Wallet, error) {
|
||||
var addr util.Uint160
|
||||
|
||||
wPath := ctx.String("wallet")
|
||||
walletConfigPath := ctx.String("wallet-config")
|
||||
if len(wPath) != 0 && len(walletConfigPath) != 0 {
|
||||
return nil, nil, errConflictingWalletFlags
|
||||
}
|
||||
if len(wPath) == 0 && len(walletConfigPath) == 0 {
|
||||
return nil, nil, errNoWallet
|
||||
}
|
||||
var pass *string
|
||||
if len(walletConfigPath) != 0 {
|
||||
cfg, err := ReadWalletConfig(walletConfigPath)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
wPath = cfg.Path
|
||||
pass = &cfg.Password
|
||||
}
|
||||
|
||||
wall, err := wallet.NewWalletFromFile(wPath)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
addrFlag := ctx.Generic("address").(*flags.Address)
|
||||
if addrFlag.IsSet {
|
||||
addr = addrFlag.Uint160()
|
||||
} else {
|
||||
addr = wall.GetChangeAddress()
|
||||
if addr.Equals(util.Uint160{}) {
|
||||
return nil, wall, errors.New("can't get default address")
|
||||
}
|
||||
}
|
||||
|
||||
acc, err := GetUnlockedAccount(wall, addr, pass)
|
||||
return acc, wall, err
|
||||
}
|
||||
|
||||
// GetUnlockedAccount returns account from wallet, address and uses pass to unlock specified account if given.
|
||||
// If the password is not given, then it is requested from user.
|
||||
func GetUnlockedAccount(wall *wallet.Wallet, addr util.Uint160, pass *string) (*wallet.Account, error) {
|
||||
acc := wall.GetAccount(addr)
|
||||
if acc == nil {
|
||||
return nil, fmt.Errorf("wallet contains no account for '%s'", address.Uint160ToString(addr))
|
||||
}
|
||||
|
||||
if acc.CanSign() || acc.EncryptedWIF == "" {
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
if pass == nil {
|
||||
rawPass, err := input.ReadPassword(
|
||||
fmt.Sprintf("Enter account %s password > ", address.Uint160ToString(addr)))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error reading password: %w", err)
|
||||
}
|
||||
trimmed := strings.TrimRight(string(rawPass), "\n")
|
||||
pass = &trimmed
|
||||
}
|
||||
err := acc.Decrypt(*pass, wall.Scrypt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// ReadWalletConfig reads wallet config from the given path.
|
||||
func ReadWalletConfig(configPath string) (*config.Wallet, error) {
|
||||
file, err := os.Open(configPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
configData, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to read wallet config: %w", err)
|
||||
}
|
||||
|
||||
cfg := &config.Wallet{}
|
||||
|
||||
err = yaml.Unmarshal(configData, &cfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal wallet config YAML: %w", err)
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package query
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
@ -203,7 +204,7 @@ func queryCandidates(ctx *cli.Context) error {
|
|||
var res []byte
|
||||
res = fmt.Appendf(res, "Key\tVotes\tCommittee\tConsensus\n")
|
||||
for _, val := range vals {
|
||||
res = fmt.Appendf(res, "%s\t%d\t%t\t%t\n", val.PublicKey.StringCompressed(), val.Votes, comm.Contains(&val.PublicKey), val.Active)
|
||||
res = fmt.Appendf(res, "%s\t%d\t%t\t%t\n", hex.EncodeToString(val.PublicKey.Bytes()), val.Votes, comm.Contains(&val.PublicKey), val.Active)
|
||||
}
|
||||
tw := tabwriter.NewWriter(ctx.App.Writer, 0, 2, 2, ' ', 0)
|
||||
_, err = tw.Write(res)
|
||||
|
@ -234,7 +235,7 @@ func queryCommittee(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
for _, k := range comm {
|
||||
fmt.Fprintln(ctx.App.Writer, k.StringCompressed())
|
||||
fmt.Fprintln(ctx.App.Writer, hex.EncodeToString(k.Bytes()))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -305,7 +306,7 @@ func queryVoter(ctx *cli.Context) error {
|
|||
}
|
||||
voted := "null"
|
||||
if st.VoteTo != nil {
|
||||
voted = fmt.Sprintf("%s (%s)", st.VoteTo.StringCompressed(), address.Uint160ToString(st.VoteTo.GetScriptHash()))
|
||||
voted = fmt.Sprintf("%s (%s)", hex.EncodeToString(st.VoteTo.Bytes()), address.Uint160ToString(st.VoteTo.GetScriptHash()))
|
||||
}
|
||||
fmt.Fprintf(ctx.App.Writer, "\tVoted: %s\n", voted)
|
||||
fmt.Fprintf(ctx.App.Writer, "\tAmount : %s\n", fixedn.ToString(&st.Balance, int(dec)))
|
||||
|
|
|
@ -498,7 +498,7 @@ func startServer(ctx *cli.Context) error {
|
|||
rpcServer := rpcsrv.New(chain, cfg.ApplicationConfiguration.RPC, serv, oracleSrv, log, errChan)
|
||||
serv.AddService(&rpcServer)
|
||||
|
||||
serv.Start()
|
||||
go serv.Start()
|
||||
if !cfg.ApplicationConfiguration.RPC.StartWhenSynchronized {
|
||||
// Run RPC server in a separate routine. This is necessary to avoid a potential
|
||||
// deadlock: Start() can write errors to errChan which is not yet read in the
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"flag"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"go.uber.org/zap/zapcore"
|
||||
|
@ -50,28 +49,7 @@ func TestGetConfigFromContext(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
require.Equal(t, netmode.TestNet, cfg.ProtocolConfiguration.Magic)
|
||||
})
|
||||
t.Run("relative-path windows", func(t *testing.T) {
|
||||
if runtime.GOOS != "windows" {
|
||||
t.Skip("skipping Windows specific test")
|
||||
}
|
||||
|
||||
set := flag.NewFlagSet("flagSet", flag.ExitOnError)
|
||||
set.String("relative-path", "..\\..\\config", "")
|
||||
set.Bool("testnet", true, "")
|
||||
set.String("config-file", ".\\testdata\\protocol.testnet.windows.yml", "")
|
||||
ctx := cli.NewContext(cli.NewApp(), set, nil)
|
||||
cfg, err := options.GetConfigFromContext(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, filepath.Join("..", "..", "config", "chains", "testnet"), cfg.ApplicationConfiguration.DBConfiguration.LevelDBOptions.DataDirectoryPath)
|
||||
require.Equal(t, "C:\\someFolder\\cn_wallet.json", cfg.ApplicationConfiguration.Consensus.UnlockWallet.Path)
|
||||
require.Equal(t, "C:\\someFolder\\notary_wallet.json", cfg.ApplicationConfiguration.P2PNotary.UnlockWallet.Path)
|
||||
})
|
||||
|
||||
t.Run("relative-path non-windows", func(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("skipping non-Windows specific test")
|
||||
}
|
||||
|
||||
t.Run("relative-path", func(t *testing.T) {
|
||||
set := flag.NewFlagSet("flagSet", flag.ExitOnError)
|
||||
set.String("relative-path", "../../config", "")
|
||||
set.Bool("testnet", true, "")
|
||||
|
@ -79,7 +57,7 @@ func TestGetConfigFromContext(t *testing.T) {
|
|||
ctx := cli.NewContext(cli.NewApp(), set, nil)
|
||||
cfg, err := options.GetConfigFromContext(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, filepath.Join("..", "..", "config", "chains", "testnet"), cfg.ApplicationConfiguration.DBConfiguration.LevelDBOptions.DataDirectoryPath)
|
||||
require.Equal(t, "../../config/chains/testnet", cfg.ApplicationConfiguration.DBConfiguration.LevelDBOptions.DataDirectoryPath)
|
||||
require.Equal(t, "/cn_wallet.json", cfg.ApplicationConfiguration.Consensus.UnlockWallet.Path)
|
||||
require.Equal(t, "/notary_wallet.json", cfg.ApplicationConfiguration.P2PNotary.UnlockWallet.Path)
|
||||
})
|
||||
|
|
96
cli/server/testdata/protocol.testnet.windows.yml
vendored
96
cli/server/testdata/protocol.testnet.windows.yml
vendored
|
@ -1,96 +0,0 @@
|
|||
ProtocolConfiguration:
|
||||
Magic: 894710606
|
||||
MaxBlockSize: 2097152
|
||||
MaxBlockSystemFee: 150000000000
|
||||
MaxTraceableBlocks: 2102400
|
||||
MaxTransactionsPerBlock: 5000
|
||||
InitialGASSupply: 52000000
|
||||
TimePerBlock: 15s
|
||||
MemPoolSize: 50000
|
||||
StandbyCommittee:
|
||||
- 023e9b32ea89b94d066e649b124fd50e396ee91369e8e2a6ae1b11c170d022256d
|
||||
- 03009b7540e10f2562e5fd8fac9eaec25166a58b26e412348ff5a86927bfac22a2
|
||||
- 02ba2c70f5996f357a43198705859fae2cfea13e1172962800772b3d588a9d4abd
|
||||
- 03408dcd416396f64783ac587ea1e1593c57d9fea880c8a6a1920e92a259477806
|
||||
- 02a7834be9b32e2981d157cb5bbd3acb42cfd11ea5c3b10224d7a44e98c5910f1b
|
||||
- 0214baf0ceea3a66f17e7e1e839ea25fd8bed6cd82e6bb6e68250189065f44ff01
|
||||
- 030205e9cefaea5a1dfc580af20c8d5aa2468bb0148f1a5e4605fc622c80e604ba
|
||||
- 025831cee3708e87d78211bec0d1bfee9f4c85ae784762f042e7f31c0d40c329b8
|
||||
- 02cf9dc6e85d581480d91e88e8cbeaa0c153a046e89ded08b4cefd851e1d7325b5
|
||||
- 03840415b0a0fcf066bcc3dc92d8349ebd33a6ab1402ef649bae00e5d9f5840828
|
||||
- 026328aae34f149853430f526ecaa9cf9c8d78a4ea82d08bdf63dd03c4d0693be6
|
||||
- 02c69a8d084ee7319cfecf5161ff257aa2d1f53e79bf6c6f164cff5d94675c38b3
|
||||
- 0207da870cedb777fceff948641021714ec815110ca111ccc7a54c168e065bda70
|
||||
- 035056669864feea401d8c31e447fb82dd29f342a9476cfd449584ce2a6165e4d7
|
||||
- 0370c75c54445565df62cfe2e76fbec4ba00d1298867972213530cae6d418da636
|
||||
- 03957af9e77282ae3263544b7b2458903624adc3f5dee303957cb6570524a5f254
|
||||
- 03d84d22b8753cf225d263a3a782a4e16ca72ef323cfde04977c74f14873ab1e4c
|
||||
- 02147c1b1d5728e1954958daff2f88ee2fa50a06890a8a9db3fa9e972b66ae559f
|
||||
- 03c609bea5a4825908027e4ab217e7efc06e311f19ecad9d417089f14927a173d5
|
||||
- 0231edee3978d46c335e851c76059166eb8878516f459e085c0dd092f0f1d51c21
|
||||
- 03184b018d6b2bc093e535519732b3fd3f7551c8cffaf4621dd5a0b89482ca66c9
|
||||
ValidatorsCount: 7
|
||||
SeedList:
|
||||
- seed1t5.neo.org:20333
|
||||
- seed2t5.neo.org:20333
|
||||
- seed3t5.neo.org:20333
|
||||
- seed4t5.neo.org:20333
|
||||
- seed5t5.neo.org:20333
|
||||
VerifyTransactions: false
|
||||
P2PSigExtensions: false
|
||||
Hardforks:
|
||||
Aspidochelone: 210000
|
||||
Basilisk: 2680000
|
||||
|
||||
ApplicationConfiguration:
|
||||
SkipBlockVerification: false
|
||||
DBConfiguration:
|
||||
Type: "leveldb" #other options: 'inmemory','boltdb'
|
||||
# DB type options. Uncomment those you need in case you want to switch DB type.
|
||||
LevelDBOptions:
|
||||
DataDirectoryPath: ".\\chains\\testnet"
|
||||
P2P:
|
||||
Addresses:
|
||||
- ":20333" # in form of "[host]:[port][:announcedPort]"
|
||||
DialTimeout: 3s
|
||||
ProtoTickInterval: 2s
|
||||
PingInterval: 30s
|
||||
PingTimeout: 90s
|
||||
MaxPeers: 100
|
||||
AttemptConnPeers: 20
|
||||
MinPeers: 10
|
||||
Relay: true
|
||||
Consensus:
|
||||
Enabled: false
|
||||
UnlockWallet:
|
||||
Path: "C:\\someFolder\\cn_wallet.json"
|
||||
Password: "pass"
|
||||
Oracle:
|
||||
Enabled: false
|
||||
AllowedContentTypes:
|
||||
- application/json
|
||||
P2PNotary:
|
||||
Enabled: false
|
||||
UnlockWallet:
|
||||
Path: "C:\\someFolder\\notary_wallet.json"
|
||||
Password: "pass"
|
||||
RPC:
|
||||
Enabled: true
|
||||
Addresses:
|
||||
- ":20332"
|
||||
MaxGasInvoke: 15
|
||||
EnableCORSWorkaround: false
|
||||
TLSConfig:
|
||||
Enabled: false
|
||||
Addresses:
|
||||
- ":20331"
|
||||
CertFile: serv.crt
|
||||
KeyFile: serv.key
|
||||
Prometheus:
|
||||
Enabled: true
|
||||
Addresses:
|
||||
- ":2112"
|
||||
Pprof:
|
||||
Enabled: false
|
||||
Addresses:
|
||||
- ":2113"
|
|
@ -25,7 +25,6 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/nef"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
|
||||
|
@ -146,7 +145,18 @@ func Blocks() []*alias.Block {
|
|||
cmd = append(cmd, "--in", ctrPath, "--bindings", bindingsPath)
|
||||
|
||||
// Replace `pkg/interop` in go.mod to avoid getting an actual module version.
|
||||
require.NoError(t, updateGoMod(ctrPath, "myimport.com/testcontract", "../../pkg/interop"))
|
||||
goMod := filepath.Join(ctrPath, "go.mod")
|
||||
data, err := os.ReadFile(goMod)
|
||||
require.NoError(t, err)
|
||||
|
||||
i := bytes.IndexByte(data, '\n')
|
||||
data = append([]byte("module myimport.com/testcontract"), data[i:]...)
|
||||
|
||||
wd, err := os.Getwd()
|
||||
require.NoError(t, err)
|
||||
data = append(data, "\nreplace github.com/nspcc-dev/neo-go/pkg/interop => "...)
|
||||
data = append(data, filepath.Join(wd, "../../pkg/interop")...)
|
||||
require.NoError(t, os.WriteFile(goMod, data, os.ModePerm))
|
||||
|
||||
cmd = append(cmd, "--config", cfgPath,
|
||||
"--out", filepath.Join(tmpDir, "out.nef"),
|
||||
|
@ -166,9 +176,9 @@ func Blocks() []*alias.Block {
|
|||
|
||||
bs, err := os.ReadFile(outPath)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, `// Code generated by neo-go contract generate-wrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
|
||||
// Package testcontract contains wrappers for testcontract contract.
|
||||
require.Equal(t, `// Package testcontract contains wrappers for testcontract contract.
|
||||
//
|
||||
// Code generated by neo-go contract generate-wrapper --manifest <file.json> --out <file.go> --hash <hash> [--config <config>]; DO NOT EDIT.
|
||||
package testcontract
|
||||
|
||||
import (
|
||||
|
@ -203,84 +213,6 @@ func ToMap(a []testcontract.MyPair) map[int]string {
|
|||
`, string(bs))
|
||||
}
|
||||
|
||||
// updateGoMod updates the go.mod file located in the specified directory.
|
||||
// It sets the module name and replaces the neo-go interop package path with
|
||||
// the provided one to avoid getting an actual module version.
|
||||
func updateGoMod(dir, moduleName, neoGoPath string) error {
|
||||
goModPath := filepath.Join(dir, "go.mod")
|
||||
data, err := os.ReadFile(goModPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read go.mod: %w", err)
|
||||
}
|
||||
|
||||
i := bytes.IndexByte(data, '\n')
|
||||
if i == -1 {
|
||||
return fmt.Errorf("unexpected go.mod format")
|
||||
}
|
||||
|
||||
updatedData := append([]byte("module "+moduleName), data[i:]...)
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get working directory: %w", err)
|
||||
}
|
||||
|
||||
replacementPath := filepath.Join(wd, neoGoPath)
|
||||
updatedData = append(updatedData, "\nreplace github.com/nspcc-dev/neo-go/pkg/interop => "+replacementPath+" \n"...)
|
||||
|
||||
if err := os.WriteFile(goModPath, updatedData, os.ModePerm); err != nil {
|
||||
return fmt.Errorf("failed to write updated go.mod: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestDynamicWrapper(t *testing.T) {
|
||||
// For proper contract init. The actual version as it will be replaced.
|
||||
smartcontract.ModVersion = "v0.0.0"
|
||||
|
||||
tmpDir := t.TempDir()
|
||||
e := testcli.NewExecutor(t, true)
|
||||
|
||||
ctrPath := "../smartcontract/testdata"
|
||||
|
||||
verifyHash := testcli.DeployContract(t, e, filepath.Join(ctrPath, "verify.go"), filepath.Join(ctrPath, "verify.yml"), testcli.ValidatorWallet, testcli.ValidatorAddr, testcli.ValidatorPass)
|
||||
|
||||
helperContract := `package testcontract
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop"
|
||||
verify "myimport.com/testcontract/bindings"
|
||||
)
|
||||
|
||||
func CallVerifyContract(h interop.Hash160) bool{
|
||||
contractInstance := verify.NewContract(h)
|
||||
return contractInstance.Verify()
|
||||
}`
|
||||
|
||||
helperDir := filepath.Join(tmpDir, "helper")
|
||||
e.Run(t, "neo-go", "contract", "init", "--name", helperDir)
|
||||
|
||||
require.NoError(t, updateGoMod(helperDir, "myimport.com/testcontract", "../../pkg/interop"))
|
||||
require.NoError(t, os.WriteFile(filepath.Join(helperDir, "main.go"), []byte(helperContract), os.ModePerm))
|
||||
require.NoError(t, os.Mkdir(filepath.Join(helperDir, "bindings"), os.ModePerm))
|
||||
|
||||
e.Run(t, "neo-go", "contract", "generate-wrapper",
|
||||
"--config", filepath.Join(ctrPath, "verify.bindings.yml"), "--manifest", filepath.Join(ctrPath, "verify.manifest.json"),
|
||||
"--out", filepath.Join(helperDir, "bindings", "testdata.go"))
|
||||
e.Run(t, "neo-go", "contract", "compile", "--in", filepath.Join(helperDir, "main.go"), "--config", filepath.Join(helperDir, "neo-go.yml"))
|
||||
helperHash := testcli.DeployContract(t, e, filepath.Join(helperDir, "main.go"), filepath.Join(helperDir, "neo-go.yml"), testcli.ValidatorWallet, testcli.ValidatorAddr, testcli.ValidatorPass)
|
||||
|
||||
e.In.WriteString("one\r")
|
||||
e.Run(t, "neo-go", "contract", "invokefunction",
|
||||
"--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
|
||||
"--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr, "--force", "--await", helperHash.StringLE(), "callVerifyContract", verifyHash.StringLE())
|
||||
|
||||
tx, _ := e.CheckTxPersisted(t, "Sent invocation transaction ")
|
||||
aer, err := e.Chain.GetAppExecResults(tx.Hash(), trigger.Application)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, aer[0].Stack[0].Value().(bool), true)
|
||||
}
|
||||
|
||||
func TestContractInitAndCompile(t *testing.T) {
|
||||
// For proper contract init. The actual version as it will be replaced.
|
||||
smartcontract.ModVersion = "v0.0.0"
|
||||
|
@ -333,7 +265,15 @@ func TestContractInitAndCompile(t *testing.T) {
|
|||
})
|
||||
|
||||
// Replace `pkg/interop` in go.mod to avoid getting an actual module version.
|
||||
require.NoError(t, updateGoMod(ctrPath, "myimport.com/testcontract", "../../pkg/interop"))
|
||||
goMod := filepath.Join(ctrPath, "go.mod")
|
||||
data, err := os.ReadFile(goMod)
|
||||
require.NoError(t, err)
|
||||
|
||||
wd, err := os.Getwd()
|
||||
require.NoError(t, err)
|
||||
data = append(data, "\nreplace github.com/nspcc-dev/neo-go/pkg/interop => "...)
|
||||
data = append(data, filepath.Join(wd, "../../pkg/interop")...)
|
||||
require.NoError(t, os.WriteFile(goMod, data, os.ModePerm))
|
||||
|
||||
cmd = append(cmd, "--config", cfgPath)
|
||||
|
||||
|
@ -398,7 +338,7 @@ func TestContractDeployWithData(t *testing.T) {
|
|||
"--config", "testdata/deploy/neo-go.yml",
|
||||
"--out", nefName, "--manifest", manifestName)
|
||||
|
||||
deployContract := func(t *testing.T, haveData bool, scope string, await bool) {
|
||||
deployContract := func(t *testing.T, haveData bool, scope string) {
|
||||
e := testcli.NewExecutor(t, true)
|
||||
cmd := []string{
|
||||
"neo-go", "contract", "deploy",
|
||||
|
@ -408,9 +348,6 @@ func TestContractDeployWithData(t *testing.T) {
|
|||
"--force",
|
||||
}
|
||||
|
||||
if await {
|
||||
cmd = append(cmd, "--await")
|
||||
}
|
||||
if haveData {
|
||||
cmd = append(cmd, "[", "key1", "12", "key2", "take_me_to_church", "]")
|
||||
}
|
||||
|
@ -421,13 +358,8 @@ func TestContractDeployWithData(t *testing.T) {
|
|||
}
|
||||
e.In.WriteString(testcli.ValidatorPass + "\r")
|
||||
e.Run(t, cmd...)
|
||||
var tx *transaction.Transaction
|
||||
if await {
|
||||
tx, _ = e.CheckAwaitableTxPersisted(t)
|
||||
} else {
|
||||
tx, _ = e.CheckTxPersisted(t)
|
||||
}
|
||||
|
||||
tx, _ := e.CheckTxPersisted(t, "Sent invocation transaction ")
|
||||
require.Equal(t, scope, tx.Signers[0].Scopes.String())
|
||||
if !haveData {
|
||||
return
|
||||
|
@ -464,12 +396,9 @@ func TestContractDeployWithData(t *testing.T) {
|
|||
require.Equal(t, []byte("take_me_to_church"), res.Stack[0].Value())
|
||||
}
|
||||
|
||||
deployContract(t, true, "", false)
|
||||
deployContract(t, false, "Global", false)
|
||||
deployContract(t, true, "Global", false)
|
||||
deployContract(t, false, "", true)
|
||||
deployContract(t, true, "Global", true)
|
||||
deployContract(t, true, "", true)
|
||||
deployContract(t, true, "")
|
||||
deployContract(t, false, "Global")
|
||||
deployContract(t, true, "Global")
|
||||
}
|
||||
|
||||
func TestDeployWithSigners(t *testing.T) {
|
||||
|
@ -843,12 +772,6 @@ func TestComlileAndInvokeFunction(t *testing.T) {
|
|||
e.Run(t, append(cmd, h.StringLE(), "getValue",
|
||||
"--", testcli.ValidatorAddr, hVerify.StringLE())...)
|
||||
})
|
||||
|
||||
t.Run("with await", func(t *testing.T) {
|
||||
e.In.WriteString("one\r")
|
||||
e.Run(t, append(cmd, "--force", "--await", h.StringLE(), "getValue")...)
|
||||
e.CheckAwaitableTxPersisted(t)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("real invoke and save tx", func(t *testing.T) {
|
||||
|
|
|
@ -30,22 +30,17 @@ var generatorFlags = []cli.Flag{
|
|||
},
|
||||
cli.StringFlag{
|
||||
Name: "hash",
|
||||
Usage: "Smart-contract hash. If not passed, the wrapper will be designed for dynamic hash usage",
|
||||
Usage: "Smart-contract hash",
|
||||
},
|
||||
}
|
||||
|
||||
var generateWrapperCmd = cli.Command{
|
||||
Name: "generate-wrapper",
|
||||
Usage: "generate wrapper to use in other contracts",
|
||||
UsageText: "neo-go contract generate-wrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]",
|
||||
Description: `Generates a Go wrapper to use it in other smart contracts. If the
|
||||
--hash flag is provided, CALLT instruction is used for the target contract
|
||||
invocation as an optimization of the wrapper contract code. If omitted, the
|
||||
generated wrapper will be designed for dynamic hash usage, allowing
|
||||
the hash to be specified at runtime.
|
||||
`,
|
||||
Action: contractGenerateWrapper,
|
||||
Flags: generatorFlags,
|
||||
Name: "generate-wrapper",
|
||||
Usage: "generate wrapper to use in other contracts",
|
||||
UsageText: "neo-go contract generate-wrapper --manifest <file.json> --out <file.go> --hash <hash> [--config <config>]",
|
||||
Description: ``,
|
||||
Action: contractGenerateWrapper,
|
||||
Flags: generatorFlags,
|
||||
}
|
||||
|
||||
var generateRPCWrapperCmd = cli.Command{
|
||||
|
@ -57,15 +52,15 @@ var generateRPCWrapperCmd = cli.Command{
|
|||
}
|
||||
|
||||
func contractGenerateWrapper(ctx *cli.Context) error {
|
||||
return contractGenerateSomething(ctx, binding.Generate)
|
||||
return contractGenerateSomething(ctx, binding.Generate, false)
|
||||
}
|
||||
|
||||
func contractGenerateRPCWrapper(ctx *cli.Context) error {
|
||||
return contractGenerateSomething(ctx, rpcbinding.Generate)
|
||||
return contractGenerateSomething(ctx, rpcbinding.Generate, true)
|
||||
}
|
||||
|
||||
// contractGenerateSomething reads generator parameters and calls the given callback.
|
||||
func contractGenerateSomething(ctx *cli.Context, cb func(binding.Config) error) error {
|
||||
func contractGenerateSomething(ctx *cli.Context, cb func(binding.Config) error, allowEmptyHash bool) error {
|
||||
if err := cmdargs.EnsureNone(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -78,6 +73,8 @@ func contractGenerateSomething(ctx *cli.Context, cb func(binding.Config) error)
|
|||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("invalid contract hash: %w", err), 1)
|
||||
}
|
||||
} else if !allowEmptyHash {
|
||||
return cli.NewExitError("contract hash must be provided via --hash flag", 1)
|
||||
}
|
||||
m, _, err := readManifest(ctx.String("manifest"), h)
|
||||
if err != nil {
|
||||
|
|
|
@ -151,9 +151,9 @@ callflags:
|
|||
"--hash", h.StringLE(),
|
||||
}))
|
||||
|
||||
const expected = `// Code generated by neo-go contract generate-wrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
|
||||
// Package wrapper contains wrappers for MyContract contract.
|
||||
const expected = `// Package wrapper contains wrappers for MyContract contract.
|
||||
//
|
||||
// Code generated by neo-go contract generate-wrapper --manifest <file.json> --out <file.go> --hash <hash> [--config <config>]; DO NOT EDIT.
|
||||
package wrapper
|
||||
|
||||
import (
|
||||
|
@ -174,8 +174,8 @@ func Sum(first int, second int) int {
|
|||
return neogointernal.CallWithToken(Hash, "sum", int(contract.All), first, second).(int)
|
||||
}
|
||||
|
||||
// Sum2 invokes ` + "`sum`" + ` method of contract.
|
||||
func Sum2(first int, second int, third int) int {
|
||||
// Sum_3 invokes ` + "`sum`" + ` method of contract.
|
||||
func Sum_3(first int, second int, third int) int {
|
||||
return neogointernal.CallWithToken(Hash, "sum", int(contract.All), first, second, third).(int)
|
||||
}
|
||||
|
||||
|
@ -233,99 +233,6 @@ func MyFunc(in map[int]mycontract.Input) []mycontract.Output {
|
|||
data, err := os.ReadFile(outFile)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expected, string(data))
|
||||
|
||||
require.NoError(t, app.Run([]string{"", "generate-wrapper",
|
||||
"--manifest", manifestFile,
|
||||
"--config", cfgPath,
|
||||
"--out", outFile,
|
||||
}))
|
||||
expectedWithDynamicHash := `// Code generated by neo-go contract generate-wrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
|
||||
// Package wrapper contains wrappers for MyContract contract.
|
||||
package wrapper
|
||||
|
||||
import (
|
||||
"github.com/heyitsme/mycontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/contract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/iterator"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/native/ledger"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/storage"
|
||||
)
|
||||
|
||||
// Contract represents the MyContract smart contract.
|
||||
type Contract struct {
|
||||
Hash interop.Hash160
|
||||
}
|
||||
|
||||
// NewContract returns a new Contract instance with the specified hash.
|
||||
func NewContract(hash interop.Hash160) Contract {
|
||||
return Contract{Hash: hash}
|
||||
}
|
||||
|
||||
// Sum invokes ` + "`sum`" + ` method of contract.
|
||||
func (c Contract) Sum(first int, second int) int {
|
||||
return contract.Call(c.Hash, "sum", contract.All, first, second).(int)
|
||||
}
|
||||
|
||||
// Sum2 invokes ` + "`sum`" + ` method of contract.
|
||||
func (c Contract) Sum2(first int, second int, third int) int {
|
||||
return contract.Call(c.Hash, "sum", contract.All, first, second, third).(int)
|
||||
}
|
||||
|
||||
// Sum3 invokes ` + "`sum3`" + ` method of contract.
|
||||
func (c Contract) Sum3() int {
|
||||
return contract.Call(c.Hash, "sum3", contract.ReadOnly).(int)
|
||||
}
|
||||
|
||||
// Zum invokes ` + "`zum`" + ` method of contract.
|
||||
func (c Contract) Zum(typev int, typev_ int, funcv int) int {
|
||||
return contract.Call(c.Hash, "zum", contract.All, typev, typev_, funcv).(int)
|
||||
}
|
||||
|
||||
// JustExecute invokes ` + "`justExecute`" + ` method of contract.
|
||||
func (c Contract) JustExecute(arr []any) {
|
||||
contract.Call(c.Hash, "justExecute", contract.All, arr)
|
||||
}
|
||||
|
||||
// GetPublicKey invokes ` + "`getPublicKey`" + ` method of contract.
|
||||
func (c Contract) GetPublicKey() interop.PublicKey {
|
||||
return contract.Call(c.Hash, "getPublicKey", contract.All).(interop.PublicKey)
|
||||
}
|
||||
|
||||
// OtherTypes invokes ` + "`otherTypes`" + ` method of contract.
|
||||
func (c Contract) OtherTypes(ctr interop.Hash160, tx interop.Hash256, sig interop.Signature, data any) bool {
|
||||
return contract.Call(c.Hash, "otherTypes", contract.All, ctr, tx, sig, data).(bool)
|
||||
}
|
||||
|
||||
// SearchStorage invokes ` + "`searchStorage`" + ` method of contract.
|
||||
func (c Contract) SearchStorage(ctx storage.Context) iterator.Iterator {
|
||||
return contract.Call(c.Hash, "searchStorage", contract.All, ctx).(iterator.Iterator)
|
||||
}
|
||||
|
||||
// GetFromMap invokes ` + "`getFromMap`" + ` method of contract.
|
||||
func (c Contract) GetFromMap(intMap map[string]int, indices []string) []int {
|
||||
return contract.Call(c.Hash, "getFromMap", contract.All, intMap, indices).([]int)
|
||||
}
|
||||
|
||||
// DoSomething invokes ` + "`doSomething`" + ` method of contract.
|
||||
func (c Contract) DoSomething(bytes []byte, str string) any {
|
||||
return contract.Call(c.Hash, "doSomething", contract.ReadStates, bytes, str).(any)
|
||||
}
|
||||
|
||||
// GetBlockWrapper invokes ` + "`getBlockWrapper`" + ` method of contract.
|
||||
func (c Contract) GetBlockWrapper() ledger.Block {
|
||||
return contract.Call(c.Hash, "getBlockWrapper", contract.All).(ledger.Block)
|
||||
}
|
||||
|
||||
// MyFunc invokes ` + "`myFunc`" + ` method of contract.
|
||||
func (c Contract) MyFunc(in map[int]mycontract.Input) []mycontract.Output {
|
||||
return contract.Call(c.Hash, "myFunc", contract.All, in).([]mycontract.Output)
|
||||
}
|
||||
`
|
||||
data, err = os.ReadFile(outFile)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedWithDynamicHash, string(data))
|
||||
}
|
||||
|
||||
func TestGenerateValidPackageName(t *testing.T) {
|
||||
|
@ -360,9 +267,9 @@ func TestGenerateValidPackageName(t *testing.T) {
|
|||
|
||||
data, err := os.ReadFile(outFile)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, `// Code generated by neo-go contract generate-wrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
|
||||
// Package myspacecontract contains wrappers for My space contract contract.
|
||||
require.Equal(t, `// Package myspacecontract contains wrappers for My space contract contract.
|
||||
//
|
||||
// Code generated by neo-go contract generate-wrapper --manifest <file.json> --out <file.go> --hash <hash> [--config <config>]; DO NOT EDIT.
|
||||
package myspacecontract
|
||||
|
||||
import (
|
||||
|
@ -386,9 +293,9 @@ func Get() int {
|
|||
|
||||
data, err = os.ReadFile(outFile)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, `// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
|
||||
// Package myspacecontract contains RPC wrappers for My space contract contract.
|
||||
require.Equal(t, `// Package myspacecontract contains RPC wrappers for My space contract contract.
|
||||
//
|
||||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
package myspacecontract
|
||||
|
||||
import (
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
|
||||
"github.com/nspcc-dev/neo-go/cli/cmdargs"
|
||||
"github.com/nspcc-dev/neo-go/cli/flags"
|
||||
"github.com/nspcc-dev/neo-go/cli/options"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/nef"
|
||||
|
@ -38,7 +37,7 @@ func manifestAddGroup(ctx *cli.Context) error {
|
|||
|
||||
h := state.CreateContractHash(sender, nf.Checksum, m.Name)
|
||||
|
||||
gAcc, w, err := options.GetAccFromContext(ctx)
|
||||
gAcc, w, err := GetAccFromContext(ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't get account to sign group with: %w", err), 1)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package smartcontract
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
|
@ -27,9 +28,10 @@ func (p permission) MarshalYAML() (any, error) {
|
|||
&yaml.Node{Kind: yaml.ScalarNode, Value: permHashKey},
|
||||
&yaml.Node{Kind: yaml.ScalarNode, Value: p.Contract.Value.(util.Uint160).StringLE()})
|
||||
case manifest.PermissionGroup:
|
||||
bs := p.Contract.Value.(*keys.PublicKey).Bytes()
|
||||
m.Content = append(m.Content,
|
||||
&yaml.Node{Kind: yaml.ScalarNode, Value: permGroupKey},
|
||||
&yaml.Node{Kind: yaml.ScalarNode, Value: p.Contract.Value.(*keys.PublicKey).StringCompressed()})
|
||||
&yaml.Node{Kind: yaml.ScalarNode, Value: hex.EncodeToString(bs)})
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid permission type: %d", p.Contract.Type)
|
||||
}
|
||||
|
|
|
@ -11,11 +11,14 @@ import (
|
|||
|
||||
"github.com/nspcc-dev/neo-go/cli/cmdargs"
|
||||
"github.com/nspcc-dev/neo-go/cli/flags"
|
||||
"github.com/nspcc-dev/neo-go/cli/input"
|
||||
"github.com/nspcc-dev/neo-go/cli/options"
|
||||
"github.com/nspcc-dev/neo-go/cli/txctx"
|
||||
cliwallet "github.com/nspcc-dev/neo-go/cli/wallet"
|
||||
"github.com/nspcc-dev/neo-go/pkg/compiler"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
|
||||
|
@ -36,14 +39,16 @@ import (
|
|||
const addressFlagName = "address, a"
|
||||
|
||||
var (
|
||||
errNoInput = errors.New("no input file was found, specify an input file with the '--in or -i' flag")
|
||||
errNoConfFile = errors.New("no config file was found, specify a config file with the '--config' or '-c' flag")
|
||||
errNoManifestFile = errors.New("no manifest file was found, specify manifest file with '--manifest' or '-m' flag")
|
||||
errNoMethod = errors.New("no method specified for function invocation command")
|
||||
errNoScriptHash = errors.New("no smart contract hash was provided, specify one as the first argument")
|
||||
errNoSmartContractName = errors.New("no name was provided, specify the '--name or -n' flag")
|
||||
errFileExist = errors.New("A file with given smart-contract name already exists")
|
||||
addressFlag = flags.AddressFlag{
|
||||
errNoInput = errors.New("no input file was found, specify an input file with the '--in or -i' flag")
|
||||
errNoConfFile = errors.New("no config file was found, specify a config file with the '--config' or '-c' flag")
|
||||
errNoManifestFile = errors.New("no manifest file was found, specify manifest file with '--manifest' or '-m' flag")
|
||||
errNoMethod = errors.New("no method specified for function invocation command")
|
||||
errNoWallet = errors.New("no wallet parameter found, specify it with the '--wallet' or '-w' flag or specify wallet config file with the '--wallet-config' flag")
|
||||
errConflictingWalletFlags = errors.New("--wallet flag conflicts with --wallet-config flag, please, provide one of them to specify wallet location")
|
||||
errNoScriptHash = errors.New("no smart contract hash was provided, specify one as the first argument")
|
||||
errNoSmartContractName = errors.New("no name was provided, specify the '--name or -n' flag")
|
||||
errFileExist = errors.New("A file with given smart-contract name already exists")
|
||||
addressFlag = flags.AddressFlag{
|
||||
Name: addressFlagName,
|
||||
Usage: "address to use as transaction signee (and gas source)",
|
||||
}
|
||||
|
@ -91,7 +96,6 @@ func NewCommands() []cli.Command {
|
|||
txctx.SysGasFlag,
|
||||
txctx.OutFlag,
|
||||
txctx.ForceFlag,
|
||||
txctx.AwaitFlag,
|
||||
}
|
||||
invokeFunctionFlags = append(invokeFunctionFlags, options.Wallet...)
|
||||
invokeFunctionFlags = append(invokeFunctionFlags, options.RPC...)
|
||||
|
@ -137,8 +141,7 @@ func NewCommands() []cli.Command {
|
|||
then the output filenames for these flags will be guessed using the contract
|
||||
name or path provided via --in option by trimming/adding corresponding suffixes
|
||||
to the common part of the path. In the latter case the configuration filepath
|
||||
will be guessed from the --in option using the same rule.
|
||||
`,
|
||||
will be guessed from the --in option using the same rule."`,
|
||||
Action: contractCompile,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
|
@ -190,12 +193,10 @@ func NewCommands() []cli.Command {
|
|||
{
|
||||
Name: "deploy",
|
||||
Usage: "deploy a smart contract (.nef with description)",
|
||||
UsageText: "neo-go contract deploy -r endpoint -w wallet [-a address] [-g gas] [-e sysgas] --in contract.nef --manifest contract.manifest.json [--out file] [--force] [--await] [data]",
|
||||
UsageText: "neo-go contract deploy -r endpoint -w wallet [-a address] [-g gas] [-e sysgas] --in contract.nef --manifest contract.manifest.json [--out file] [--force] [data]",
|
||||
Description: `Deploys given contract into the chain. The gas parameter is for additional
|
||||
gas to be added as a network fee to prioritize the transaction. The data
|
||||
parameter is an optional parameter to be passed to '_deploy' method. When
|
||||
--await flag is specified, it waits for the transaction to be included
|
||||
in a block.
|
||||
parameter is an optional parameter to be passed to '_deploy' method.
|
||||
`,
|
||||
Action: contractDeploy,
|
||||
Flags: deployFlags,
|
||||
|
@ -205,14 +206,13 @@ func NewCommands() []cli.Command {
|
|||
{
|
||||
Name: "invokefunction",
|
||||
Usage: "invoke deployed contract on the blockchain",
|
||||
UsageText: "neo-go contract invokefunction -r endpoint -w wallet [-a address] [-g gas] [-e sysgas] [--out file] [--force] [--await] scripthash [method] [arguments...] [--] [signers...]",
|
||||
UsageText: "neo-go contract invokefunction -r endpoint -w wallet [-a address] [-g gas] [-e sysgas] [--out file] [--force] scripthash [method] [arguments...] [--] [signers...]",
|
||||
Description: `Executes given (as a script hash) deployed script with the given method,
|
||||
arguments and signers. Sender is included in the list of signers by default
|
||||
with None witness scope. If you'd like to change default sender's scope,
|
||||
specify it via signers parameter. See testinvokefunction documentation for
|
||||
the details about parameters. It differs from testinvokefunction in that this
|
||||
command sends an invocation transaction to the network. When --await flag is
|
||||
specified, it waits for the transaction to be included in a block.
|
||||
command sends an invocation transaction to the network.
|
||||
`,
|
||||
Action: invokeFunction,
|
||||
Flags: invokeFunctionFlags,
|
||||
|
@ -375,9 +375,6 @@ func initSmartContract(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
gm := []byte("module " + contractName + `
|
||||
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/nspcc-dev/neo-go/pkg/interop ` + ver + `
|
||||
)`)
|
||||
|
@ -573,7 +570,7 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error {
|
|||
w *wallet.Wallet
|
||||
)
|
||||
if signAndPush {
|
||||
acc, w, err = options.GetAccFromContext(ctx)
|
||||
acc, w, err = GetAccFromContext(ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
|
@ -600,14 +597,19 @@ func invokeWithArgs(ctx *cli.Context, acc *wallet.Account, wall *wallet.Wallet,
|
|||
}
|
||||
gctx, cancel := options.GetTimeoutContext(ctx)
|
||||
defer cancel()
|
||||
|
||||
c, err := options.GetRPCClient(gctx, ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if signAndPush {
|
||||
_, act, err = options.GetRPCWithActor(gctx, ctx, signersAccounts)
|
||||
act, err = actor.New(c, signersAccounts)
|
||||
if err != nil {
|
||||
return err
|
||||
return cli.NewExitError(fmt.Errorf("failed to create RPC actor: %w", err), 1)
|
||||
}
|
||||
inv = &act.Invoker
|
||||
} else {
|
||||
_, inv, err = options.GetRPCWithInvoker(gctx, ctx, cosigners)
|
||||
inv, err = options.GetInvoker(c, ctx, cosigners)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -744,6 +746,71 @@ func inspect(ctx *cli.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// GetAccFromContext returns account and wallet from context. If address is not set, default address is used.
|
||||
func GetAccFromContext(ctx *cli.Context) (*wallet.Account, *wallet.Wallet, error) {
|
||||
var addr util.Uint160
|
||||
|
||||
wPath := ctx.String("wallet")
|
||||
walletConfigPath := ctx.String("wallet-config")
|
||||
if len(wPath) != 0 && len(walletConfigPath) != 0 {
|
||||
return nil, nil, errConflictingWalletFlags
|
||||
}
|
||||
if len(wPath) == 0 && len(walletConfigPath) == 0 {
|
||||
return nil, nil, errNoWallet
|
||||
}
|
||||
var pass *string
|
||||
if len(walletConfigPath) != 0 {
|
||||
cfg, err := cliwallet.ReadWalletConfig(walletConfigPath)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
wPath = cfg.Path
|
||||
pass = &cfg.Password
|
||||
}
|
||||
|
||||
wall, err := wallet.NewWalletFromFile(wPath)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
addrFlag := ctx.Generic("address").(*flags.Address)
|
||||
if addrFlag.IsSet {
|
||||
addr = addrFlag.Uint160()
|
||||
} else {
|
||||
addr = wall.GetChangeAddress()
|
||||
}
|
||||
|
||||
acc, err := GetUnlockedAccount(wall, addr, pass)
|
||||
return acc, wall, err
|
||||
}
|
||||
|
||||
// GetUnlockedAccount returns account from wallet, address and uses pass to unlock specified account if given.
|
||||
// If the password is not given, then it is requested from user.
|
||||
func GetUnlockedAccount(wall *wallet.Wallet, addr util.Uint160, pass *string) (*wallet.Account, error) {
|
||||
acc := wall.GetAccount(addr)
|
||||
if acc == nil {
|
||||
return nil, fmt.Errorf("wallet contains no account for '%s'", address.Uint160ToString(addr))
|
||||
}
|
||||
|
||||
if acc.CanSign() {
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
if pass == nil {
|
||||
rawPass, err := input.ReadPassword(
|
||||
fmt.Sprintf("Enter account %s password > ", address.Uint160ToString(addr)))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error reading password: %w", err)
|
||||
}
|
||||
trimmed := strings.TrimRight(string(rawPass), "\n")
|
||||
pass = &trimmed
|
||||
}
|
||||
err := acc.Decrypt(*pass, wall.Scrypt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// contractDeploy deploys contract.
|
||||
func contractDeploy(ctx *cli.Context) error {
|
||||
nefFile, f, err := readNEFFile(ctx.String("in"))
|
||||
|
@ -769,7 +836,7 @@ func contractDeploy(ctx *cli.Context) error {
|
|||
appCallParams = append(appCallParams, data[0])
|
||||
}
|
||||
|
||||
acc, w, err := options.GetAccFromContext(ctx)
|
||||
acc, w, err := GetAccFromContext(ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't get sender address: %w", err), 1)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package smartcontract
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"flag"
|
||||
"os"
|
||||
"testing"
|
||||
|
@ -108,7 +109,7 @@ func TestPermissionMarshal(t *testing.T) {
|
|||
p.Methods.Add("abc")
|
||||
p.Methods.Add("lamao")
|
||||
testPermissionMarshal(t, p,
|
||||
"group: "+priv.PublicKey().StringCompressed()+"\n"+
|
||||
"group: "+hex.EncodeToString(priv.PublicKey().Bytes())+"\n"+
|
||||
"methods:\n - abc\n - lamao\n")
|
||||
})
|
||||
}
|
||||
|
@ -117,7 +118,7 @@ func TestPermissionUnmarshalInvalid(t *testing.T) {
|
|||
priv, err := keys.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
pub := priv.PublicKey().StringCompressed()
|
||||
pub := hex.EncodeToString(priv.PublicKey().Bytes())
|
||||
u160 := random.Uint160().StringLE()
|
||||
testCases := []string{
|
||||
"hash: []\nmethods: '*'\n", // invalid hash type
|
||||
|
|
4
cli/smartcontract/testdata/gas/gas.go
vendored
4
cli/smartcontract/testdata/gas/gas.go
vendored
|
@ -1,6 +1,6 @@
|
|||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
|
||||
// Package gastoken contains RPC wrappers for GasToken contract.
|
||||
//
|
||||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
package gastoken
|
||||
|
||||
import (
|
||||
|
|
16
cli/smartcontract/testdata/nameservice/nns.go
vendored
16
cli/smartcontract/testdata/nameservice/nns.go
vendored
|
@ -1,6 +1,6 @@
|
|||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
|
||||
// Package nameservice contains RPC wrappers for NameService contract.
|
||||
//
|
||||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
package nameservice
|
||||
|
||||
import (
|
||||
|
@ -256,25 +256,25 @@ func (c *Contract) RenewUnsigned(name string) (*transaction.Transaction, error)
|
|||
return c.actor.MakeUnsignedCall(c.hash, "renew", nil, name)
|
||||
}
|
||||
|
||||
// Renew2 creates a transaction invoking `renew` method of the contract.
|
||||
// Renew_2 creates a transaction invoking `renew` method of the contract.
|
||||
// This transaction is signed and immediately sent to the network.
|
||||
// The values returned are its hash, ValidUntilBlock value and error if any.
|
||||
func (c *Contract) Renew2(name string, years *big.Int) (util.Uint256, uint32, error) {
|
||||
func (c *Contract) Renew_2(name string, years *big.Int) (util.Uint256, uint32, error) {
|
||||
return c.actor.SendCall(c.hash, "renew", name, years)
|
||||
}
|
||||
|
||||
// Renew2Transaction creates a transaction invoking `renew` method of the contract.
|
||||
// Renew_2Transaction creates a transaction invoking `renew` method of the contract.
|
||||
// This transaction is signed, but not sent to the network, instead it's
|
||||
// returned to the caller.
|
||||
func (c *Contract) Renew2Transaction(name string, years *big.Int) (*transaction.Transaction, error) {
|
||||
func (c *Contract) Renew_2Transaction(name string, years *big.Int) (*transaction.Transaction, error) {
|
||||
return c.actor.MakeCall(c.hash, "renew", name, years)
|
||||
}
|
||||
|
||||
// Renew2Unsigned creates a transaction invoking `renew` method of the contract.
|
||||
// Renew_2Unsigned creates a transaction invoking `renew` method of the contract.
|
||||
// This transaction is not signed, it's simply returned to the caller.
|
||||
// Any fields of it that do not affect fees can be changed (ValidUntilBlock,
|
||||
// Nonce), fee values (NetworkFee, SystemFee) can be increased as well.
|
||||
func (c *Contract) Renew2Unsigned(name string, years *big.Int) (*transaction.Transaction, error) {
|
||||
func (c *Contract) Renew_2Unsigned(name string, years *big.Int) (*transaction.Transaction, error) {
|
||||
return c.actor.MakeUnsignedCall(c.hash, "renew", nil, name, years)
|
||||
}
|
||||
|
||||
|
|
4
cli/smartcontract/testdata/nex/nex.go
vendored
4
cli/smartcontract/testdata/nex/nex.go
vendored
|
@ -1,6 +1,6 @@
|
|||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
|
||||
// Package nextoken contains RPC wrappers for NEX Token contract.
|
||||
//
|
||||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
package nextoken
|
||||
|
||||
import (
|
||||
|
|
4
cli/smartcontract/testdata/nonepiter/iter.go
vendored
4
cli/smartcontract/testdata/nonepiter/iter.go
vendored
|
@ -1,6 +1,6 @@
|
|||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
|
||||
// Package nonnepxxcontractwithiterators contains RPC wrappers for Non-NEPXX contract with iterators contract.
|
||||
//
|
||||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
package nonnepxxcontractwithiterators
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
|
||||
// Package structs contains RPC wrappers for Notifications contract.
|
||||
//
|
||||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
package structs
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
|
||||
// Package structs contains RPC wrappers for Notifications contract.
|
||||
//
|
||||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
package structs
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
|
||||
// Package structs contains RPC wrappers for Notifications contract.
|
||||
//
|
||||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
package structs
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
|
||||
// Package structs contains RPC wrappers for Types contract.
|
||||
//
|
||||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
package structs
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
|
||||
// Package structs contains RPC wrappers for Types contract.
|
||||
//
|
||||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
package structs
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
|
||||
// Package types contains RPC wrappers for Types contract.
|
||||
//
|
||||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
package types
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
|
||||
// Package types contains RPC wrappers for Types contract.
|
||||
//
|
||||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
package types
|
||||
|
||||
import (
|
||||
|
|
297
cli/smartcontract/testdata/verify.bindings.yml
vendored
297
cli/smartcontract/testdata/verify.bindings.yml
vendored
|
@ -1,297 +0,0 @@
|
|||
package: testdata
|
||||
hash: "0x0000000000000000000000000000000000000000"
|
||||
overrides:
|
||||
burnGas.gas: int
|
||||
call: any
|
||||
call.args: '[]any'
|
||||
call.f: any
|
||||
call.method: string
|
||||
call.scriptHash: github.com/nspcc-dev/neo-go/pkg/interop.Hash160
|
||||
callWithToken: any
|
||||
callWithToken.args: '[]any'
|
||||
callWithToken.flags: int
|
||||
callWithToken.method: string
|
||||
callWithToken.scriptHash: string
|
||||
callWithTokenNoRet.args: '[]any'
|
||||
callWithTokenNoRet.flags: int
|
||||
callWithTokenNoRet.method: string
|
||||
callWithTokenNoRet.scriptHash: string
|
||||
checkWitness: bool
|
||||
checkWitness.hashOrKey: '[]byte'
|
||||
createMultisigAccount: '[]byte'
|
||||
createMultisigAccount.m: int
|
||||
createMultisigAccount.pubs: '[]github.com/nspcc-dev/neo-go/pkg/interop.PublicKey'
|
||||
createStandardAccount: '[]byte'
|
||||
createStandardAccount.pub: github.com/nspcc-dev/neo-go/pkg/interop.PublicKey
|
||||
currentHash: github.com/nspcc-dev/neo-go/pkg/interop.Hash256
|
||||
currentIndex: int
|
||||
currentSigners: '[]github.com/nspcc-dev/neo-go/pkg/interop/native/ledger.TransactionSigner'
|
||||
equals: bool
|
||||
equals.b: any
|
||||
gasLeft: int
|
||||
getAddressVersion: int
|
||||
getBlock: '*github.com/nspcc-dev/neo-go/pkg/interop/native/ledger.Block'
|
||||
getBlock.indexOrHash: any
|
||||
getCallFlags: any
|
||||
getCallingScriptHash: github.com/nspcc-dev/neo-go/pkg/interop.Hash160
|
||||
getEntryScriptHash: github.com/nspcc-dev/neo-go/pkg/interop.Hash160
|
||||
getExecutingScriptHash: github.com/nspcc-dev/neo-go/pkg/interop.Hash160
|
||||
getInvocationCounter: int
|
||||
getNetwork: int
|
||||
getNotifications: '[][]any'
|
||||
getNotifications.h: github.com/nspcc-dev/neo-go/pkg/interop.Hash160
|
||||
getRandom: int
|
||||
getScriptContainer: '*github.com/nspcc-dev/neo-go/pkg/interop/native/ledger.Transaction'
|
||||
getTime: int
|
||||
getTransaction: '*github.com/nspcc-dev/neo-go/pkg/interop/native/ledger.Transaction'
|
||||
getTransaction.hash: github.com/nspcc-dev/neo-go/pkg/interop.Hash256
|
||||
getTransactionFromBlock: '*github.com/nspcc-dev/neo-go/pkg/interop/native/ledger.Transaction'
|
||||
getTransactionFromBlock.indexOrHash: any
|
||||
getTransactionFromBlock.txIndex: int
|
||||
getTransactionHeight: int
|
||||
getTransactionHeight.hash: github.com/nspcc-dev/neo-go/pkg/interop.Hash256
|
||||
getTransactionSigners: '[]github.com/nspcc-dev/neo-go/pkg/interop/native/ledger.TransactionSigner'
|
||||
getTransactionSigners.hash: github.com/nspcc-dev/neo-go/pkg/interop.Hash256
|
||||
getTransactionVMState: int
|
||||
getTransactionVMState.hash: github.com/nspcc-dev/neo-go/pkg/interop.Hash256
|
||||
getTrigger: int
|
||||
loadScript: any
|
||||
loadScript.args: '[]any'
|
||||
loadScript.f: any
|
||||
loadScript.script: '[]byte'
|
||||
log.message: string
|
||||
notify.args: '[]any'
|
||||
notify.name: string
|
||||
onNEP11Payment.amount: int
|
||||
onNEP11Payment.data: any
|
||||
onNEP11Payment.from: github.com/nspcc-dev/neo-go/pkg/interop.Hash160
|
||||
onNEP11Payment.token: '[]byte'
|
||||
onNEP17Payment.amount: int
|
||||
onNEP17Payment.data: any
|
||||
onNEP17Payment.from: github.com/nspcc-dev/neo-go/pkg/interop.Hash160
|
||||
opcode0NoReturn.op: string
|
||||
opcode1: any
|
||||
opcode1NoReturn.arg: any
|
||||
opcode1NoReturn.op: string
|
||||
opcode1.arg: any
|
||||
opcode1.op: string
|
||||
opcode2: any
|
||||
opcode2NoReturn.arg1: any
|
||||
opcode2NoReturn.arg2: any
|
||||
opcode2NoReturn.op: string
|
||||
opcode2.arg1: any
|
||||
opcode2.arg2: any
|
||||
opcode2.op: string
|
||||
opcode3: any
|
||||
opcode3.arg1: any
|
||||
opcode3.arg2: any
|
||||
opcode3.arg3: any
|
||||
opcode3.op: string
|
||||
platform: '[]byte'
|
||||
syscall0: any
|
||||
syscall0NoReturn.name: string
|
||||
syscall0.name: string
|
||||
syscall1: any
|
||||
syscall1NoReturn.arg: any
|
||||
syscall1NoReturn.name: string
|
||||
syscall1.arg: any
|
||||
syscall1.name: string
|
||||
syscall2: any
|
||||
syscall2NoReturn.arg1: any
|
||||
syscall2NoReturn.arg2: any
|
||||
syscall2NoReturn.name: string
|
||||
syscall2.arg1: any
|
||||
syscall2.arg2: any
|
||||
syscall2.name: string
|
||||
syscall3: any
|
||||
syscall3NoReturn.arg1: any
|
||||
syscall3NoReturn.arg2: any
|
||||
syscall3NoReturn.arg3: any
|
||||
syscall3NoReturn.name: string
|
||||
syscall3.arg1: any
|
||||
syscall3.arg2: any
|
||||
syscall3.arg3: any
|
||||
syscall3.name: string
|
||||
syscall4: any
|
||||
syscall4NoReturn.arg1: any
|
||||
syscall4NoReturn.arg2: any
|
||||
syscall4NoReturn.arg3: any
|
||||
syscall4NoReturn.arg4: any
|
||||
syscall4NoReturn.name: string
|
||||
syscall4.arg1: any
|
||||
syscall4.arg2: any
|
||||
syscall4.arg3: any
|
||||
syscall4.arg4: any
|
||||
syscall4.name: string
|
||||
toBlockSR: '*github.com/nspcc-dev/neo-go/pkg/interop/native/ledger.BlockSR'
|
||||
verify: bool
|
||||
namedtypes:
|
||||
ledger.Block:
|
||||
base: Array
|
||||
name: ledger.Block
|
||||
fields:
|
||||
- field: Hash
|
||||
base: Hash256
|
||||
- field: Version
|
||||
base: Integer
|
||||
- field: PrevHash
|
||||
base: Hash256
|
||||
- field: MerkleRoot
|
||||
base: Hash256
|
||||
- field: Timestamp
|
||||
base: Integer
|
||||
- field: Nonce
|
||||
base: Integer
|
||||
- field: Index
|
||||
base: Integer
|
||||
- field: NextConsensus
|
||||
base: Hash160
|
||||
- field: TransactionsLength
|
||||
base: Integer
|
||||
ledger.BlockSR:
|
||||
base: Array
|
||||
name: ledger.BlockSR
|
||||
fields:
|
||||
- field: Hash
|
||||
base: Hash256
|
||||
- field: Version
|
||||
base: Integer
|
||||
- field: PrevHash
|
||||
base: Hash256
|
||||
- field: MerkleRoot
|
||||
base: Hash256
|
||||
- field: Timestamp
|
||||
base: Integer
|
||||
- field: Nonce
|
||||
base: Integer
|
||||
- field: Index
|
||||
base: Integer
|
||||
- field: NextConsensus
|
||||
base: Hash160
|
||||
- field: TransactionsLength
|
||||
base: Integer
|
||||
- field: PrevStateRoot
|
||||
base: Hash256
|
||||
ledger.Transaction:
|
||||
base: Array
|
||||
name: ledger.Transaction
|
||||
fields:
|
||||
- field: Hash
|
||||
base: Hash256
|
||||
- field: Version
|
||||
base: Integer
|
||||
- field: Nonce
|
||||
base: Integer
|
||||
- field: Sender
|
||||
base: Hash160
|
||||
- field: SysFee
|
||||
base: Integer
|
||||
- field: NetFee
|
||||
base: Integer
|
||||
- field: ValidUntilBlock
|
||||
base: Integer
|
||||
- field: Script
|
||||
base: ByteArray
|
||||
ledger.TransactionSigner:
|
||||
base: Array
|
||||
name: ledger.TransactionSigner
|
||||
fields:
|
||||
- field: Account
|
||||
base: Hash160
|
||||
- field: Scopes
|
||||
base: Integer
|
||||
- field: AllowedContracts
|
||||
base: Array
|
||||
value:
|
||||
base: Hash160
|
||||
- field: AllowedGroups
|
||||
base: Array
|
||||
value:
|
||||
base: PublicKey
|
||||
- field: Rules
|
||||
base: Array
|
||||
value:
|
||||
base: Array
|
||||
name: ledger.WitnessRule
|
||||
ledger.WitnessCondition:
|
||||
base: Array
|
||||
name: ledger.WitnessCondition
|
||||
fields:
|
||||
- field: Type
|
||||
base: Integer
|
||||
- field: Value
|
||||
base: Any
|
||||
ledger.WitnessRule:
|
||||
base: Array
|
||||
name: ledger.WitnessRule
|
||||
fields:
|
||||
- field: Action
|
||||
base: Integer
|
||||
- field: Condition
|
||||
base: Array
|
||||
name: ledger.WitnessCondition
|
||||
types:
|
||||
call.args:
|
||||
base: Array
|
||||
value:
|
||||
base: Any
|
||||
call.f:
|
||||
base: InteropInterface
|
||||
interface: iterator
|
||||
callWithToken.args:
|
||||
base: Array
|
||||
value:
|
||||
base: Any
|
||||
callWithTokenNoRet.args:
|
||||
base: Array
|
||||
value:
|
||||
base: Any
|
||||
createMultisigAccount.pubs:
|
||||
base: Array
|
||||
value:
|
||||
base: PublicKey
|
||||
currentSigners:
|
||||
base: Array
|
||||
value:
|
||||
base: Array
|
||||
name: ledger.TransactionSigner
|
||||
getBlock:
|
||||
base: Array
|
||||
name: ledger.Block
|
||||
getCallFlags:
|
||||
base: InteropInterface
|
||||
interface: iterator
|
||||
getNotifications:
|
||||
base: Array
|
||||
value:
|
||||
base: Array
|
||||
value:
|
||||
base: Any
|
||||
getScriptContainer:
|
||||
base: Array
|
||||
name: ledger.Transaction
|
||||
getTransaction:
|
||||
base: Array
|
||||
name: ledger.Transaction
|
||||
getTransactionFromBlock:
|
||||
base: Array
|
||||
name: ledger.Transaction
|
||||
getTransactionSigners:
|
||||
base: Array
|
||||
value:
|
||||
base: Array
|
||||
name: ledger.TransactionSigner
|
||||
loadScript.args:
|
||||
base: Array
|
||||
value:
|
||||
base: Any
|
||||
loadScript.f:
|
||||
base: InteropInterface
|
||||
interface: iterator
|
||||
notify.args:
|
||||
base: Array
|
||||
value:
|
||||
base: Any
|
||||
toBlockSR:
|
||||
base: Array
|
||||
name: ledger.BlockSR
|
|
@ -1,6 +1,6 @@
|
|||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
|
||||
// Package verify contains RPC wrappers for verify contract.
|
||||
//
|
||||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
|
||||
package verify
|
||||
|
||||
import (
|
||||
|
|
2
cli/testdata/testwallet.json
vendored
2
cli/testdata/testwallet.json
vendored
|
@ -27,4 +27,4 @@
|
|||
"extra": {
|
||||
"Tokens": null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
64
cli/testdata/testwallet_multi.json
vendored
64
cli/testdata/testwallet_multi.json
vendored
|
@ -1,64 +0,0 @@
|
|||
{
|
||||
"version": "1.0",
|
||||
"accounts": [
|
||||
{
|
||||
"address": "NgHcPxgEKZQV4QBedzyASJrgiANhJqBVLw",
|
||||
"key": "6PYTbVq2P3AJQwWU5SFMKLjHYco7QABtNRo4ZvLvXhyaYjwMcuZm6xKokT",
|
||||
"label": "one",
|
||||
"contract": {
|
||||
"script": "DCECnmSGVirDOqMr57EHaYz0YMTjaHQtO9FQYu8DMTCDw6VBVuezJw==",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "parameter0",
|
||||
"type": "Signature"
|
||||
}
|
||||
],
|
||||
"deployed": false
|
||||
},
|
||||
"lock": false,
|
||||
"isDefault": false
|
||||
},
|
||||
{
|
||||
"address": "NLvHRfKAifjio2z9HiwLo9ZnpRPHUbAHgH",
|
||||
"key": "6PYUjQ8TgR3cduEpG5niUNuPEWi3tYiQsnC4Jha9nGAJ6tAQGUmcrZXsLF",
|
||||
"label": "two",
|
||||
"contract": {
|
||||
"script": "DCECgk91c1ABAX3A1uJNnxhGlp7NwUJScwJzJhrsYrXIbgNBVuezJw==",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "parameter0",
|
||||
"type": "Signature"
|
||||
}
|
||||
],
|
||||
"deployed": false
|
||||
},
|
||||
"lock": false,
|
||||
"isDefault": false
|
||||
},
|
||||
{
|
||||
"address": "NcDfG8foJx79XSihcDDrx1df7cHAoJBfXj",
|
||||
"key": "6PYRkUQKWFrTovHyeQZ7X4nWoDXKohtFRKW51LiCz317pwCjmB1cVwpcxz",
|
||||
"label": "three",
|
||||
"contract": {
|
||||
"script": "DCEC9v0ZqBg8f4jJX9WR891M0bazf0FYTNu7MEgpSHrb9CVBVuezJw==",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "parameter0",
|
||||
"type": "Signature"
|
||||
}
|
||||
],
|
||||
"deployed": false
|
||||
},
|
||||
"lock": false,
|
||||
"isDefault": false
|
||||
}
|
||||
],
|
||||
"scrypt": {
|
||||
"n": 2,
|
||||
"r": 1,
|
||||
"p": 1
|
||||
},
|
||||
"extra": {
|
||||
"Tokens": null
|
||||
}
|
||||
}
|
2
cli/testdata/wallet1_solo.json
vendored
2
cli/testdata/wallet1_solo.json
vendored
|
@ -80,4 +80,4 @@
|
|||
"extra": {
|
||||
"Tokens": null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,16 +5,13 @@ package txctx
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/cli/flags"
|
||||
"github.com/nspcc-dev/neo-go/cli/input"
|
||||
"github.com/nspcc-dev/neo-go/cli/paramcontext"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
@ -40,11 +37,6 @@ var (
|
|||
Name: "force",
|
||||
Usage: "Do not ask for a confirmation (and ignore errors)",
|
||||
}
|
||||
// AwaitFlag is a flag used to wait for the transaction to be included in a block.
|
||||
AwaitFlag = cli.BoolFlag{
|
||||
Name: "await",
|
||||
Usage: "wait for the transaction to be included in a block",
|
||||
}
|
||||
)
|
||||
|
||||
// SignAndSend adds network and system fees to the provided transaction and
|
||||
|
@ -56,7 +48,6 @@ func SignAndSend(ctx *cli.Context, act *actor.Actor, acc *wallet.Account, tx *tr
|
|||
gas = flags.Fixed8FromContext(ctx, "gas")
|
||||
sysgas = flags.Fixed8FromContext(ctx, "sysgas")
|
||||
ver = act.GetVersion()
|
||||
aer *state.AppExecResult
|
||||
)
|
||||
|
||||
tx.SystemFee += int64(sysgas)
|
||||
|
@ -75,39 +66,14 @@ func SignAndSend(ctx *cli.Context, act *actor.Actor, acc *wallet.Account, tx *tr
|
|||
}
|
||||
waitTime := time.Since(promptTime)
|
||||
// Compensate for confirmation waiting.
|
||||
tx.ValidUntilBlock += uint32(waitTime.Milliseconds()/int64(ver.Protocol.MillisecondsPerBlock)) + 2
|
||||
}
|
||||
var (
|
||||
resTx util.Uint256
|
||||
vub uint32
|
||||
)
|
||||
resTx, vub, err = act.SignAndSend(tx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
if ctx.Bool("await") {
|
||||
aer, err = act.Wait(resTx, vub, err)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to await transaction %s: %w", resTx.StringLE(), err), 1)
|
||||
}
|
||||
tx.ValidUntilBlock += uint32((waitTime.Milliseconds() / int64(ver.Protocol.MillisecondsPerBlock))) + 1
|
||||
}
|
||||
_, _, err = act.SignAndSend(tx)
|
||||
}
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
|
||||
DumpTransactionInfo(ctx.App.Writer, tx.Hash(), aer)
|
||||
fmt.Fprintln(ctx.App.Writer, tx.Hash().StringLE())
|
||||
return nil
|
||||
}
|
||||
|
||||
// DumpTransactionInfo prints transaction info to the given writer.
|
||||
func DumpTransactionInfo(w io.Writer, h util.Uint256, res *state.AppExecResult) {
|
||||
fmt.Fprintln(w, h.StringLE())
|
||||
if res != nil {
|
||||
fmt.Fprintf(w, "OnChain:\t%t\n", res != nil)
|
||||
fmt.Fprintf(w, "VMState:\t%s\n", res.VMState.String())
|
||||
if res.FaultException != "" {
|
||||
fmt.Fprintf(w, "FaultException:\t%s\n", res.FaultException)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,15 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/cli/cmdargs"
|
||||
"github.com/nspcc-dev/neo-go/cli/flags"
|
||||
"github.com/nspcc-dev/neo-go/cli/options"
|
||||
"github.com/nspcc-dev/neo-go/cli/txctx"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||
"github.com/nspcc-dev/neo-go/cli/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/waiter"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||
"github.com/urfave/cli"
|
||||
|
@ -35,31 +31,31 @@ func cancelTx(ctx *cli.Context) error {
|
|||
gctx, cancel := options.GetTimeoutContext(ctx)
|
||||
defer cancel()
|
||||
|
||||
acc, w, err := options.GetAccFromContext(ctx)
|
||||
c, err := options.GetRPCClient(gctx, ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to create RPC client: %w", err), 1)
|
||||
}
|
||||
|
||||
mainTx, _ := c.GetRawTransactionVerbose(txHash)
|
||||
if mainTx != nil && !mainTx.Blockhash.Equals(util.Uint256{}) {
|
||||
return cli.NewExitError(fmt.Errorf("transaction %s is already accepted at block %s", txHash, mainTx.Blockhash.StringLE()), 1)
|
||||
}
|
||||
acc, w, err := smartcontract.GetAccFromContext(ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to get account from context to sign the conflicting transaction: %w", err), 1)
|
||||
}
|
||||
defer w.Close()
|
||||
|
||||
signers, err := cmdargs.GetSignersAccounts(acc, w, nil, transaction.CalledByEntry)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("invalid signers: %w", err), 1)
|
||||
}
|
||||
c, a, exitErr := options.GetRPCWithActor(gctx, ctx, signers)
|
||||
if exitErr != nil {
|
||||
return exitErr
|
||||
}
|
||||
|
||||
mainTx, _ := c.GetRawTransactionVerbose(txHash)
|
||||
if mainTx != nil && !mainTx.Blockhash.Equals(util.Uint256{}) {
|
||||
return cli.NewExitError(fmt.Errorf("target transaction %s is accepted at block %s", txHash, mainTx.Blockhash.StringLE()), 1)
|
||||
}
|
||||
|
||||
if mainTx != nil && !mainTx.HasSigner(acc.ScriptHash()) {
|
||||
return cli.NewExitError(fmt.Errorf("account %s is not a signer of the conflicting transaction", acc.Address), 1)
|
||||
}
|
||||
|
||||
resHash, resVub, err := a.SendTunedRun([]byte{byte(opcode.RET)}, []transaction.Attribute{{Type: transaction.ConflictsT, Value: &transaction.Conflicts{Hash: txHash}}}, func(r *result.Invoke, t *transaction.Transaction) error {
|
||||
a, err := actor.NewSimple(c, acc)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to create Actor: %w", err), 1)
|
||||
}
|
||||
|
||||
resHash, _, err := a.SendTunedRun([]byte{byte(opcode.RET)}, []transaction.Attribute{{Type: transaction.ConflictsT, Value: &transaction.Conflicts{Hash: txHash}}}, func(r *result.Invoke, t *transaction.Transaction) error {
|
||||
err := actor.DefaultCheckerModifier(r, t)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -68,36 +64,11 @@ func cancelTx(ctx *cli.Context) error {
|
|||
t.NetworkFee = mainTx.NetworkFee + 1
|
||||
}
|
||||
t.NetworkFee += int64(flags.Fixed8FromContext(ctx, "gas"))
|
||||
if mainTx != nil {
|
||||
t.ValidUntilBlock = mainTx.ValidUntilBlock
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to send conflicting transaction: %w", err), 1)
|
||||
}
|
||||
var res *state.AppExecResult
|
||||
if ctx.Bool("await") {
|
||||
res, err = a.WaitAny(gctx, resVub, txHash, resHash)
|
||||
if err != nil {
|
||||
if errors.Is(err, waiter.ErrTxNotAccepted) {
|
||||
if mainTx == nil {
|
||||
return cli.NewExitError(fmt.Errorf("neither target nor conflicting transaction is accepted before the current height %d (ValidUntilBlock value of conlicting transaction). Main transaction is unknown to the provided RPC node, thus still has chances to be accepted, you may try cancellation again", resVub), 1)
|
||||
}
|
||||
fmt.Fprintf(ctx.App.Writer, "Neither target nor conflicting transaction is accepted before the current height %d (ValidUntilBlock value of both target and conflicting transactions). Main transaction is not valid anymore, cancellation is successful\n", resVub)
|
||||
return nil
|
||||
}
|
||||
return cli.NewExitError(fmt.Errorf("failed to await target/ conflicting transaction %s/ %s: %w", txHash.StringLE(), resHash.StringLE(), err), 1)
|
||||
}
|
||||
if txHash.Equals(res.Container) {
|
||||
tx, err := c.GetRawTransactionVerbose(txHash)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("target transaction %s is accepted", txHash), 1)
|
||||
}
|
||||
return cli.NewExitError(fmt.Errorf("target transaction %s is accepted at block %s", txHash, tx.Blockhash.StringLE()), 1)
|
||||
}
|
||||
fmt.Fprintln(ctx.App.Writer, "Conflicting transaction accepted")
|
||||
}
|
||||
txctx.DumpTransactionInfo(ctx.App.Writer, resHash, res)
|
||||
fmt.Fprintln(ctx.App.Writer, resHash.StringLE())
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -17,14 +17,12 @@ import (
|
|||
// NewCommands returns util commands for neo-go CLI.
|
||||
func NewCommands() []cli.Command {
|
||||
txDumpFlags := append([]cli.Flag{}, options.RPC...)
|
||||
txSendFlags := append(txDumpFlags, txctx.AwaitFlag)
|
||||
txCancelFlags := append([]cli.Flag{
|
||||
flags.AddressFlag{
|
||||
Name: "address, a",
|
||||
Usage: "address to use as conflicting transaction signee (and gas source)",
|
||||
},
|
||||
txctx.GasFlag,
|
||||
txctx.AwaitFlag,
|
||||
}, options.RPC...)
|
||||
txCancelFlags = append(txCancelFlags, options.Wallet...)
|
||||
return []cli.Command{
|
||||
|
@ -44,32 +42,29 @@ func NewCommands() []cli.Command {
|
|||
{
|
||||
Name: "sendtx",
|
||||
Usage: "Send complete transaction stored in a context file",
|
||||
UsageText: "sendtx [-r <endpoint>] <file.in> [--await]",
|
||||
UsageText: "sendtx [-r <endpoint>] <file.in>",
|
||||
Description: `Sends the transaction from the given context file to the given RPC node if it's
|
||||
completely signed and ready. This command expects a ContractParametersContext
|
||||
JSON file for input, it can't handle binary (or hex- or base64-encoded)
|
||||
transactions. If the --await flag is included, the command waits for the
|
||||
transaction to be included in a block before exiting.
|
||||
transactions.
|
||||
`,
|
||||
Action: sendTx,
|
||||
Flags: txSendFlags,
|
||||
Flags: txDumpFlags,
|
||||
},
|
||||
{
|
||||
Name: "canceltx",
|
||||
Usage: "Cancel transaction by sending conflicting transaction",
|
||||
UsageText: "canceltx <txid> -r <endpoint> --wallet <wallet> [--account <account>] [--wallet-config <path>] [--gas <gas>] [--await]",
|
||||
UsageText: "canceltx <txid> -r <endpoint> --wallet <wallet> [--account <account>] [--wallet-config <path>] [--gas <gas>]",
|
||||
Description: `Aims to prevent a transaction from being added to the blockchain by dispatching a more
|
||||
prioritized conflicting transaction to the specified RPC node. The input for this command should
|
||||
be the transaction hash. If another account is not specified, the conflicting transaction is
|
||||
automatically generated and signed by the default account in the wallet. If the target transaction
|
||||
is in the memory pool of the provided RPC node, the NetworkFee value of the conflicting transaction
|
||||
is set to the target transaction's NetworkFee value plus one (if it's sufficient for the
|
||||
conflicting transaction itself), the ValidUntilBlock value of the conflicting transaction is set to the
|
||||
target transaction's ValidUntilBlock value. If the target transaction is not in the memory pool, standard
|
||||
NetworkFee calculations are performed based on the calculatenetworkfee RPC request. If the --gas
|
||||
flag is included, the specified value is added to the resulting conflicting transaction network fee
|
||||
in both scenarios. When the --await flag is included, the command waits for one of the conflicting
|
||||
or target transactions to be included in a block.
|
||||
prioritized conflicting transaction to the specified RPC node. The input for this command should
|
||||
be the transaction hash. If another account is not specified, the conflicting transaction is
|
||||
automatically generated and signed by the default account in the wallet. If the target transaction
|
||||
is in the memory pool of the provided RPC node, the NetworkFee value of the conflicting transaction
|
||||
is set to the target transaction's NetworkFee value plus one (if it's sufficient for the
|
||||
conflicting transaction itself). If the target transaction is not in the memory pool, standard
|
||||
NetworkFee calculations are performed based on the calculatenetworkfee RPC request. If the --gas
|
||||
flag is included, the specified value is added to the resulting conflicting transaction network fee
|
||||
in both scenarios.
|
||||
`,
|
||||
Action: cancelTx,
|
||||
Flags: txCancelFlags,
|
||||
|
@ -80,12 +75,6 @@ func NewCommands() []cli.Command {
|
|||
UsageText: "txdump [-r <endpoint>] <file.in>",
|
||||
Action: txDump,
|
||||
Flags: txDumpFlags,
|
||||
Description: `Dumps the transaction from the given parameter context file to
|
||||
the output. This command expects a ContractParametersContext JSON file for input, it can't handle
|
||||
binary (or hex- or base64-encoded) transactions. If --rpc-endpoint flag is specified the result
|
||||
of the given script after running it true the VM will be printed. Otherwise only transaction will
|
||||
be printed.
|
||||
`,
|
||||
},
|
||||
{
|
||||
Name: "ops",
|
||||
|
|
|
@ -5,9 +5,6 @@ import (
|
|||
|
||||
"github.com/nspcc-dev/neo-go/cli/options"
|
||||
"github.com/nspcc-dev/neo-go/cli/paramcontext"
|
||||
"github.com/nspcc-dev/neo-go/cli/txctx"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/waiter"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
|
@ -40,14 +37,6 @@ func sendTx(ctx *cli.Context) error {
|
|||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to submit transaction to RPC node: %w", err), 1)
|
||||
}
|
||||
var aer *state.AppExecResult
|
||||
if ctx.Bool("await") {
|
||||
version, err := c.GetVersion()
|
||||
aer, err = waiter.New(c, version).Wait(res, tx.ValidUntilBlock, err)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to await transaction %s: %w", res.StringLE(), err), 1)
|
||||
}
|
||||
}
|
||||
txctx.DumpTransactionInfo(ctx.App.Writer, res, aer)
|
||||
fmt.Fprintln(ctx.App.Writer, res.StringLE())
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
package util_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/internal/testcli"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -139,54 +136,3 @@ func TestUtilCancelTx(t *testing.T) {
|
|||
return aerErr == nil
|
||||
}, time.Second*2, time.Millisecond*50)
|
||||
}
|
||||
|
||||
func TestAwaitUtilCancelTx(t *testing.T) {
|
||||
e := testcli.NewExecutor(t, true)
|
||||
|
||||
w, err := wallet.NewWalletFromFile("../testdata/testwallet.json")
|
||||
require.NoError(t, err)
|
||||
|
||||
transferArgs := []string{
|
||||
"neo-go", "wallet", "nep17", "transfer",
|
||||
"--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
|
||||
"--wallet", testcli.ValidatorWallet,
|
||||
"--to", w.Accounts[0].Address,
|
||||
"--token", "NEO",
|
||||
"--from", testcli.ValidatorAddr,
|
||||
"--force",
|
||||
}
|
||||
args := []string{"neo-go", "util", "canceltx",
|
||||
"-r", "http://" + e.RPC.Addresses()[0],
|
||||
"--wallet", testcli.ValidatorWallet,
|
||||
"--address", testcli.ValidatorAddr,
|
||||
"--await"}
|
||||
|
||||
e.In.WriteString("one\r")
|
||||
e.Run(t, append(transferArgs, "--amount", "1")...)
|
||||
line := e.GetNextLine(t)
|
||||
txHash, err := util.Uint256DecodeStringLE(line)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, ok := e.Chain.GetMemPool().TryGetValue(txHash)
|
||||
require.True(t, ok)
|
||||
|
||||
// Allow both cases: either target or conflicting tx acceptance.
|
||||
e.In.WriteString("one\r")
|
||||
err = e.RunUnchecked(t, append(args, txHash.StringLE())...)
|
||||
switch {
|
||||
case err == nil:
|
||||
response := e.GetNextLine(t)
|
||||
require.Equal(t, "Conflicting transaction accepted", response)
|
||||
resHash, _ := e.CheckAwaitableTxPersisted(t)
|
||||
require.NotEqual(t, resHash, txHash)
|
||||
case strings.Contains(err.Error(), fmt.Sprintf("target transaction %s is accepted", txHash)) ||
|
||||
strings.Contains(err.Error(), fmt.Sprintf("failed to send conflicting transaction: Invalid transaction attribute (-507) - invalid attribute: conflicting transaction %s is already on chain", txHash)):
|
||||
tx, _ := e.GetTransaction(t, txHash)
|
||||
aer, err := e.Chain.GetAppExecResults(tx.Hash(), trigger.Application)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(aer))
|
||||
require.Equal(t, vmstate.Halt, aer[0].VMState)
|
||||
default:
|
||||
t.Fatal(fmt.Errorf("unexpected error: %w", err))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -616,7 +616,7 @@ func getInstructionParameter(c *cli.Context) (int, error) {
|
|||
}
|
||||
n, err := strconv.Atoi(args[0])
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("%w: %w", ErrInvalidParameter, err)
|
||||
return 0, fmt.Errorf("%w: %s", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
@ -736,7 +736,7 @@ func handleLoadNEF(c *cli.Context) error {
|
|||
if signersStartOffset != 0 && len(args) > signersStartOffset {
|
||||
signers, err = cmdargs.ParseSigners(c.Args()[signersStartOffset:])
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: failed to parse signers: %w", ErrInvalidParameter, err)
|
||||
return fmt.Errorf("%w: failed to parse signers: %v", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors
|
||||
}
|
||||
}
|
||||
err = prepareVM(c, createFakeTransaction(nef.Script, signers))
|
||||
|
@ -767,7 +767,7 @@ func handleLoadBase64(c *cli.Context) error {
|
|||
}
|
||||
b, err := base64.StdEncoding.DecodeString(args[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: %w", ErrInvalidParameter, err)
|
||||
return fmt.Errorf("%w: %s", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors
|
||||
}
|
||||
var signers []transaction.Signer
|
||||
if len(args) > 1 {
|
||||
|
@ -779,7 +779,7 @@ func handleLoadBase64(c *cli.Context) error {
|
|||
}
|
||||
signers, err = cmdargs.ParseSigners(args[2:])
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: %w", ErrInvalidParameter, err)
|
||||
return fmt.Errorf("%w: %v", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors
|
||||
}
|
||||
}
|
||||
err = prepareVM(c, createFakeTransaction(b, signers))
|
||||
|
@ -807,7 +807,7 @@ func handleLoadHex(c *cli.Context) error {
|
|||
}
|
||||
b, err := hex.DecodeString(args[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: %w", ErrInvalidParameter, err)
|
||||
return fmt.Errorf("%w: %s", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors
|
||||
}
|
||||
var signers []transaction.Signer
|
||||
if len(args) > 1 {
|
||||
|
@ -819,7 +819,7 @@ func handleLoadHex(c *cli.Context) error {
|
|||
}
|
||||
signers, err = cmdargs.ParseSigners(args[2:])
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: %w", ErrInvalidParameter, err)
|
||||
return fmt.Errorf("%w: %v", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors
|
||||
}
|
||||
}
|
||||
err = prepareVM(c, createFakeTransaction(b, signers))
|
||||
|
@ -859,7 +859,7 @@ func handleLoadGo(c *cli.Context) error {
|
|||
}
|
||||
signers, err = cmdargs.ParseSigners(args[2:])
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: %w", ErrInvalidParameter, err)
|
||||
return fmt.Errorf("%w: %v", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -962,7 +962,7 @@ func handleLoadDeployed(c *cli.Context) error {
|
|||
}
|
||||
signers, err = cmdargs.ParseSigners(args[2:])
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: %w", ErrInvalidParameter, err)
|
||||
return fmt.Errorf("%w: %v", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors
|
||||
}
|
||||
}
|
||||
err = prepareVM(c, createFakeTransaction(cs.NEF.Script, signers)) // prepare VM one more time for proper IC initialization.
|
||||
|
@ -1074,7 +1074,7 @@ func handleRun(c *cli.Context) error {
|
|||
|
||||
_, scParams, err := cmdargs.ParseParams(args[1:], true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: %w", ErrInvalidParameter, err)
|
||||
return fmt.Errorf("%w: %v", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors
|
||||
}
|
||||
params = make([]stackitem.Item, len(scParams))
|
||||
for i := range scParams {
|
||||
|
@ -1105,7 +1105,7 @@ func handleRun(c *cli.Context) error {
|
|||
breaks := v.Context().BreakPoints() // We ensure that there's a context loaded.
|
||||
ic.ReuseVM(v)
|
||||
v.GasLimit = gasLimit
|
||||
v.LoadNEFMethod(&cs.NEF, &cs.Manifest, util.Uint160{}, cs.Hash, callflag.All, hasRet, offset, initOff, nil)
|
||||
v.LoadNEFMethod(&cs.NEF, util.Uint160{}, cs.Hash, callflag.All, hasRet, offset, initOff, nil)
|
||||
for _, bp := range breaks {
|
||||
v.AddBreakPoint(bp)
|
||||
}
|
||||
|
@ -1185,7 +1185,7 @@ func handleStep(c *cli.Context) error {
|
|||
if len(args) > 0 {
|
||||
n, err = strconv.Atoi(args[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: %w", ErrInvalidParameter, err)
|
||||
return fmt.Errorf("%w: %s", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors
|
||||
}
|
||||
}
|
||||
v.AddBreakPointRel(n)
|
||||
|
|
|
@ -93,11 +93,12 @@ func newTestVMCLIWithLogoAndCustomConfig(t *testing.T, printLogo bool, cfg *conf
|
|||
}
|
||||
var c config.Config
|
||||
if cfg == nil {
|
||||
configPath := filepath.Join("..", "..", "config", "protocol.unit_testnet.single.yml")
|
||||
configPath := "../../config/protocol.unit_testnet.single.yml"
|
||||
var err error
|
||||
c, err = config.LoadFile(configPath, filepath.Join("..", "..", "config"))
|
||||
c, err = config.LoadFile(configPath, "../../config")
|
||||
require.NoError(t, err, "could not load chain config")
|
||||
require.Equal(t, filepath.Join("..", "..", "testdata", "wallet1_solo.json"), c.ApplicationConfiguration.Consensus.UnlockWallet.Path)
|
||||
require.Equal(t, "../../testdata/wallet1_solo.json", c.ApplicationConfiguration.Consensus.UnlockWallet.Path)
|
||||
require.Equal(t, "/notary_wallet.json", c.ApplicationConfiguration.P2PNotary.UnlockWallet.Path)
|
||||
c.ApplicationConfiguration.DBConfiguration.Type = dbconfig.InMemoryDB
|
||||
} else {
|
||||
c = *cfg
|
||||
|
@ -134,10 +135,6 @@ func newTestVMClIWithState(t *testing.T) *executor {
|
|||
}
|
||||
bc, validators, committee, err := chain.NewMultiWithCustomConfigAndStoreNoCheck(t, customConfig, store)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Save config for future usage.
|
||||
protoCfg := bc.GetConfig()
|
||||
|
||||
go bc.Run()
|
||||
e := neotest.NewExecutor(t, bc, validators, committee)
|
||||
basicchain.InitSimple(t, "../../", e)
|
||||
|
@ -149,9 +146,7 @@ func newTestVMClIWithState(t *testing.T) *executor {
|
|||
require.NoError(t, err)
|
||||
cfg.ApplicationConfiguration.DBConfiguration.Type = dbconfig.LevelDB
|
||||
cfg.ApplicationConfiguration.DBConfiguration.LevelDBOptions = opts
|
||||
cfg.ProtocolConfiguration.StateRootInHeader = protoCfg.StateRootInHeader
|
||||
cfg.ProtocolConfiguration.P2PStateExchangeExtensions = protoCfg.P2PStateExchangeExtensions
|
||||
cfg.ProtocolConfiguration.Hardforks = protoCfg.Hardforks
|
||||
cfg.ProtocolConfiguration.StateRootInHeader = true
|
||||
return newTestVMCLIWithLogoAndCustomConfig(t, false, &cfg)
|
||||
}
|
||||
|
||||
|
@ -353,7 +348,7 @@ require (
|
|||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0
|
||||
)
|
||||
replace github.com/nspcc-dev/neo-go/pkg/interop => ` + filepath.Join(wd, "../../pkg/interop") + `
|
||||
go 1.20`)
|
||||
go 1.19`)
|
||||
require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "go.mod"), goMod, os.ModePerm))
|
||||
return filename
|
||||
}
|
||||
|
@ -687,7 +682,6 @@ func TestLoad_RunWithCALLT(t *testing.T) {
|
|||
e.runProg(t,
|
||||
"loaddeployed "+cH.StringLE()+" -- NbrUYaZgyhSkNoRo9ugRyEMdUZxrhkNaWB:Global", // the contract's owner got from the contract's code.
|
||||
"run destroy",
|
||||
"exit",
|
||||
)
|
||||
e.checkNextLine(t, "READY: loaded \\d* instructions")
|
||||
e.checkStack(t) // Nothing on stack, successful execution.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package wallet_test
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
@ -17,7 +18,7 @@ func TestRegisterCandidate(t *testing.T) {
|
|||
|
||||
validatorAddress := testcli.ValidatorPriv.Address()
|
||||
validatorPublic := testcli.ValidatorPriv.PublicKey()
|
||||
validatorHex := validatorPublic.StringCompressed()
|
||||
validatorHex := hex.EncodeToString(validatorPublic.Bytes())
|
||||
|
||||
e.In.WriteString("one\r")
|
||||
e.Run(t, "neo-go", "wallet", "nep17", "multitransfer",
|
||||
|
@ -158,61 +159,4 @@ func TestRegisterCandidate(t *testing.T) {
|
|||
e.RunWithError(t, "neo-go", "query", "voter", "--rpc-endpoint", "http://"+e.RPC.Addresses()[0], validatorAddress, validatorAddress)
|
||||
e.RunWithError(t, "neo-go", "query", "committee", "--rpc-endpoint", "http://"+e.RPC.Addresses()[0], "something")
|
||||
e.RunWithError(t, "neo-go", "query", "candidates", "--rpc-endpoint", "http://"+e.RPC.Addresses()[0], "something")
|
||||
|
||||
t.Run("VoteUnvote await", func(t *testing.T) {
|
||||
e.In.WriteString("one\r")
|
||||
e.Run(t, "neo-go", "wallet", "candidate", "register",
|
||||
"--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
|
||||
"--wallet", testcli.ValidatorWallet,
|
||||
"--address", validatorAddress,
|
||||
"--force", "--await")
|
||||
e.CheckAwaitableTxPersisted(t)
|
||||
|
||||
e.In.WriteString("one\r")
|
||||
e.Run(t, "neo-go", "wallet", "candidate", "vote",
|
||||
"--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
|
||||
"--wallet", testcli.ValidatorWallet,
|
||||
"--address", validatorAddress,
|
||||
"--candidate", validatorHex,
|
||||
"--force",
|
||||
"--await")
|
||||
|
||||
e.CheckAwaitableTxPersisted(t)
|
||||
b, _ := e.Chain.GetGoverningTokenBalance(testcli.ValidatorPriv.GetScriptHash())
|
||||
|
||||
// unvote
|
||||
e.In.WriteString("one\r")
|
||||
e.Run(t, "neo-go", "wallet", "candidate", "vote",
|
||||
"--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
|
||||
"--wallet", testcli.ValidatorWallet,
|
||||
"--address", validatorAddress,
|
||||
"--force", "--await")
|
||||
_, index := e.CheckAwaitableTxPersisted(t)
|
||||
|
||||
vs, err = e.Chain.GetEnrollments()
|
||||
require.Equal(t, 1, len(vs))
|
||||
require.Equal(t, validatorPublic, vs[0].Key)
|
||||
require.Equal(t, big.NewInt(0), vs[0].Votes)
|
||||
|
||||
// check state
|
||||
e.Run(t, "neo-go", "query", "voter",
|
||||
"--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
|
||||
validatorAddress)
|
||||
e.CheckNextLine(t, "^\\s*Voted:\\s+"+"null") // no vote.
|
||||
e.CheckNextLine(t, "^\\s*Amount\\s*:\\s*"+b.String()+"$")
|
||||
e.CheckNextLine(t, "^\\s*Block\\s*:\\s*"+strconv.FormatUint(uint64(index), 10))
|
||||
e.CheckEOF(t)
|
||||
})
|
||||
|
||||
e.In.WriteString("one\r")
|
||||
e.Run(t, "neo-go", "wallet", "candidate", "unregister",
|
||||
"--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
|
||||
"--wallet", testcli.ValidatorWallet,
|
||||
"--address", validatorAddress,
|
||||
"--force",
|
||||
"--await")
|
||||
e.CheckAwaitableTxPersisted(t)
|
||||
|
||||
vs, err = e.Chain.GetEnrollments()
|
||||
require.Equal(t, 0, len(vs))
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"errors"
|
||||
"os"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/cli/options"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
|
@ -47,7 +46,7 @@ func newWalletV2FromFile(path string, configPath string) (*walletV2, *string, er
|
|||
}
|
||||
var pass *string
|
||||
if len(configPath) != 0 {
|
||||
cfg, err := options.ReadWalletConfig(configPath)
|
||||
cfg, err := ReadWalletConfig(configPath)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package wallet
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/elliptic"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util/slice"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
@ -36,27 +36,27 @@ func TestParseMultisigContract(t *testing.T) {
|
|||
testParseMultisigContract(t, s, 1, pub)
|
||||
})
|
||||
t.Run("bad, no check multisig", func(t *testing.T) {
|
||||
sBad := bytes.Clone(s)
|
||||
sBad := slice.Copy(s)
|
||||
sBad[len(sBad)-1] ^= 0xFF
|
||||
testParseMultisigContract(t, sBad, 0)
|
||||
})
|
||||
t.Run("bad, invalid number of keys", func(t *testing.T) {
|
||||
sBad := bytes.Clone(s)
|
||||
sBad := slice.Copy(s)
|
||||
sBad[len(sBad)-2] = opPush1 + 1
|
||||
testParseMultisigContract(t, sBad, 0)
|
||||
})
|
||||
t.Run("bad, invalid first instruction", func(t *testing.T) {
|
||||
sBad := bytes.Clone(s)
|
||||
sBad := slice.Copy(s)
|
||||
sBad[0] = 0xFF
|
||||
testParseMultisigContract(t, sBad, 0)
|
||||
})
|
||||
t.Run("bad, invalid public key", func(t *testing.T) {
|
||||
sBad := bytes.Clone(s)
|
||||
sBad := slice.Copy(s)
|
||||
sBad[2] = 0xFF
|
||||
testParseMultisigContract(t, sBad, 0)
|
||||
})
|
||||
t.Run("bad, many sigs", func(t *testing.T) {
|
||||
sBad := bytes.Clone(s)
|
||||
sBad := slice.Copy(s)
|
||||
sBad[0] = opPush1 + 1
|
||||
testParseMultisigContract(t, sBad, 0)
|
||||
})
|
||||
|
|
|
@ -8,10 +8,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/cli/flags"
|
||||
"github.com/nspcc-dev/neo-go/cli/options"
|
||||
"github.com/nspcc-dev/neo-go/cli/paramcontext"
|
||||
"github.com/nspcc-dev/neo-go/cli/txctx"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/waiter"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
|
@ -20,11 +17,15 @@ func signStoredTransaction(ctx *cli.Context) error {
|
|||
out = ctx.String("out")
|
||||
rpcNode = ctx.String(options.RPCEndpointFlag)
|
||||
addrFlag = ctx.Generic("address").(*flags.Address)
|
||||
aer *state.AppExecResult
|
||||
)
|
||||
if err := cmdargs.EnsureNone(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
wall, pass, err := readWallet(ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
defer wall.Close()
|
||||
|
||||
pc, err := paramcontext.Read(ctx.String("in"))
|
||||
if err != nil {
|
||||
|
@ -34,7 +35,9 @@ func signStoredTransaction(ctx *cli.Context) error {
|
|||
if !addrFlag.IsSet {
|
||||
return cli.NewExitError("address was not provided", 1)
|
||||
}
|
||||
acc, _, err := options.GetAccFromContext(ctx)
|
||||
|
||||
var ch = addrFlag.Uint160()
|
||||
acc, err := getDecryptedAccount(wall, ch, pass)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
|
@ -44,13 +47,20 @@ func signStoredTransaction(ctx *cli.Context) error {
|
|||
return cli.NewExitError("verifiable item is not a transaction", 1)
|
||||
}
|
||||
|
||||
if !tx.HasSigner(acc.ScriptHash()) {
|
||||
signerFound := false
|
||||
for i := range tx.Signers {
|
||||
if tx.Signers[i].Account == ch {
|
||||
signerFound = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !signerFound {
|
||||
return cli.NewExitError("tx signers don't contain provided account", 1)
|
||||
}
|
||||
|
||||
if acc.CanSign() {
|
||||
sign := acc.SignHashable(pc.Network, pc.Verifiable)
|
||||
if err := pc.AddSignature(acc.ScriptHash(), acc.Contract, acc.PublicKey(), sign); err != nil {
|
||||
if err := pc.AddSignature(ch, acc.Contract, acc.PublicKey(), sign); err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't add signature: %w", err), 1)
|
||||
}
|
||||
} else if rpcNode == "" {
|
||||
|
@ -88,15 +98,10 @@ func signStoredTransaction(ctx *cli.Context) error {
|
|||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to submit transaction to RPC node: %w", err), 1)
|
||||
}
|
||||
if ctx.Bool("await") {
|
||||
version, err := c.GetVersion()
|
||||
aer, err = waiter.New(c, version).Wait(res, tx.ValidUntilBlock, err)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to await transaction %s: %w", res.StringLE(), err), 1)
|
||||
}
|
||||
}
|
||||
fmt.Fprintln(ctx.App.Writer, res.StringLE())
|
||||
return nil
|
||||
}
|
||||
|
||||
txctx.DumpTransactionInfo(ctx.App.Writer, tx.Hash(), aer)
|
||||
fmt.Fprintln(ctx.App.Writer, tx.Hash().StringLE())
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package wallet_test
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
@ -44,9 +45,9 @@ func TestSignMultisigTx(t *testing.T) {
|
|||
"--wallet", w,
|
||||
"--wif", wif,
|
||||
"--min", "2",
|
||||
pubs[0].StringCompressed(),
|
||||
pubs[1].StringCompressed(),
|
||||
pubs[2].StringCompressed())
|
||||
hex.EncodeToString(pubs[0].Bytes()),
|
||||
hex.EncodeToString(pubs[1].Bytes()),
|
||||
hex.EncodeToString(pubs[2].Bytes()))
|
||||
}
|
||||
addAccount(wallet1Path, privs[0].WIF())
|
||||
addAccount(wallet2Path, privs[1].WIF())
|
||||
|
|
|
@ -101,7 +101,7 @@ func newNEP11Commands() []cli.Command {
|
|||
{
|
||||
Name: "transfer",
|
||||
Usage: "transfer NEP-11 tokens",
|
||||
UsageText: "transfer -w wallet [--wallet-config path] --rpc-endpoint <node> --timeout <time> --from <addr> --to <addr> --token <hash-or-name> --id <token-id> [--amount string] [--await] [data] [-- <cosigner1:Scope> [<cosigner2> [...]]]",
|
||||
UsageText: "transfer -w wallet [--wallet-config path] --rpc-endpoint <node> --timeout <time> --from <addr> --to <addr> --token <hash-or-name> --id <token-id> [--amount string] [data] [-- <cosigner1:Scope> [<cosigner2> [...]]]",
|
||||
Action: transferNEP11,
|
||||
Flags: transferFlags,
|
||||
Description: `Transfers specified NEP-11 token with optional cosigners list attached to
|
||||
|
@ -110,8 +110,7 @@ func newNEP11Commands() []cli.Command {
|
|||
'contract testinvokefunction' documentation for the details
|
||||
about cosigners syntax. If no cosigners are given then the
|
||||
sender with CalledByEntry scope will be used as the only
|
||||
signer. If --await flag is set then the command will wait
|
||||
for the transaction to be included in a block.
|
||||
signer.
|
||||
`,
|
||||
},
|
||||
{
|
||||
|
|
|
@ -70,7 +70,6 @@ var (
|
|||
txctx.GasFlag,
|
||||
txctx.SysGasFlag,
|
||||
txctx.ForceFlag,
|
||||
txctx.AwaitFlag,
|
||||
cli.StringFlag{
|
||||
Name: "amount",
|
||||
Usage: "Amount of asset to send",
|
||||
|
@ -84,7 +83,6 @@ var (
|
|||
txctx.GasFlag,
|
||||
txctx.SysGasFlag,
|
||||
txctx.ForceFlag,
|
||||
txctx.AwaitFlag,
|
||||
}, options.RPC...)
|
||||
)
|
||||
|
||||
|
@ -149,22 +147,20 @@ func newNEP17Commands() []cli.Command {
|
|||
{
|
||||
Name: "transfer",
|
||||
Usage: "transfer NEP-17 tokens",
|
||||
UsageText: "transfer -w wallet [--wallet-config path] [--await] --rpc-endpoint <node> --timeout <time> --from <addr> --to <addr> --token <hash-or-name> --amount string [data] [-- <cosigner1:Scope> [<cosigner2> [...]]]",
|
||||
UsageText: "transfer -w wallet [--wallet-config path] --rpc-endpoint <node> --timeout <time> --from <addr> --to <addr> --token <hash-or-name> --amount string [data] [-- <cosigner1:Scope> [<cosigner2> [...]]]",
|
||||
Action: transferNEP17,
|
||||
Flags: transferFlags,
|
||||
Description: `Transfers specified NEP-17 token amount with optional 'data' parameter and cosigners
|
||||
list attached to the transfer. See 'contract testinvokefunction' documentation
|
||||
for the details about 'data' parameter and cosigners syntax. If no 'data' is
|
||||
given then default nil value will be used. If no cosigners are given then the
|
||||
sender with CalledByEntry scope will be used as the only signer. When --await
|
||||
flag is used, the command waits for the transaction to be included in a block
|
||||
before exiting.
|
||||
sender with CalledByEntry scope will be used as the only signer.
|
||||
`,
|
||||
},
|
||||
{
|
||||
Name: "multitransfer",
|
||||
Usage: "transfer NEP-17 tokens to multiple recipients",
|
||||
UsageText: `multitransfer -w wallet [--wallet-config path] [--await] --rpc-endpoint <node> --timeout <time> --from <addr>` +
|
||||
UsageText: `multitransfer -w wallet [--wallet-config path] --rpc-endpoint <node> --timeout <time> --from <addr>` +
|
||||
` <token1>:<addr1>:<amount1> [<token2>:<addr2>:<amount2> [...]] [-- <cosigner1:Scope> [<cosigner2> [...]]]`,
|
||||
Action: multiTransferNEP17,
|
||||
Flags: multiTransferFlags,
|
||||
|
@ -526,7 +522,7 @@ func multiTransferNEP17(ctx *cli.Context) error {
|
|||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
acc, err := options.GetUnlockedAccount(wall, from, pass)
|
||||
acc, err := getDecryptedAccount(wall, from, pass)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
|
@ -534,36 +530,25 @@ func multiTransferNEP17(ctx *cli.Context) error {
|
|||
gctx, cancel := options.GetTimeoutContext(ctx)
|
||||
defer cancel()
|
||||
|
||||
c, err := options.GetRPCClient(gctx, ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
|
||||
if ctx.NArg() == 0 {
|
||||
return cli.NewExitError("empty recipients list", 1)
|
||||
}
|
||||
var (
|
||||
recipients []transferTarget
|
||||
cosignersSepPos = ctx.NArg() // `--` position.
|
||||
cosignersOffset = ctx.NArg()
|
||||
)
|
||||
cache := make(map[string]*wallet.Token)
|
||||
for i := 0; i < ctx.NArg(); i++ {
|
||||
arg := ctx.Args().Get(i)
|
||||
if arg == cmdargs.CosignersSeparator {
|
||||
cosignersSepPos = i
|
||||
cosignersOffset = i + 1
|
||||
break
|
||||
}
|
||||
}
|
||||
cosigners, extErr := cmdargs.GetSignersFromContext(ctx, cosignersSepPos+1)
|
||||
if extErr != nil {
|
||||
return extErr
|
||||
}
|
||||
signersAccounts, err := cmdargs.GetSignersAccounts(acc, wall, cosigners, transaction.CalledByEntry)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("invalid signers: %w", err), 1)
|
||||
}
|
||||
c, act, exitErr := options.GetRPCWithActor(gctx, ctx, signersAccounts)
|
||||
if exitErr != nil {
|
||||
return exitErr
|
||||
}
|
||||
|
||||
cache := make(map[string]*wallet.Token)
|
||||
for i := 0; i < cosignersSepPos; i++ {
|
||||
arg := ctx.Args().Get(i)
|
||||
ss := strings.SplitN(arg, ":", 3)
|
||||
if len(ss) != 3 {
|
||||
return cli.NewExitError("send format must be '<token>:<addr>:<amount>", 1)
|
||||
|
@ -595,6 +580,19 @@ func multiTransferNEP17(ctx *cli.Context) error {
|
|||
})
|
||||
}
|
||||
|
||||
cosigners, extErr := cmdargs.GetSignersFromContext(ctx, cosignersOffset)
|
||||
if extErr != nil {
|
||||
return extErr
|
||||
}
|
||||
signersAccounts, err := cmdargs.GetSignersAccounts(acc, wall, cosigners, transaction.CalledByEntry)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("invalid signers: %w", err), 1)
|
||||
}
|
||||
act, err := actor.New(c, signersAccounts)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to create RPC actor: %w", err), 1)
|
||||
}
|
||||
|
||||
tx, err := makeMultiTransferNEP17(act, recipients)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("can't make transaction: %w", err), 1)
|
||||
|
@ -620,7 +618,7 @@ func transferNEP(ctx *cli.Context, standard string) error {
|
|||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
acc, err := options.GetUnlockedAccount(wall, from, pass)
|
||||
acc, err := getDecryptedAccount(wall, from, pass)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
|
@ -628,22 +626,9 @@ func transferNEP(ctx *cli.Context, standard string) error {
|
|||
gctx, cancel := options.GetTimeoutContext(ctx)
|
||||
defer cancel()
|
||||
|
||||
cosignersOffset, data, extErr := cmdargs.GetDataFromContext(ctx)
|
||||
if extErr != nil {
|
||||
return extErr
|
||||
}
|
||||
cosigners, extErr := cmdargs.GetSignersFromContext(ctx, cosignersOffset)
|
||||
if extErr != nil {
|
||||
return extErr
|
||||
}
|
||||
signersAccounts, err := cmdargs.GetSignersAccounts(acc, wall, cosigners, transaction.CalledByEntry)
|
||||
c, err := options.GetRPCClient(gctx, ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("invalid signers: %w", err), 1)
|
||||
}
|
||||
|
||||
c, act, exitErr := options.GetRPCWithActor(gctx, ctx, signersAccounts)
|
||||
if exitErr != nil {
|
||||
return exitErr
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
|
||||
toFlag := ctx.Generic("to").(*flags.Address)
|
||||
|
@ -659,6 +644,24 @@ func transferNEP(ctx *cli.Context, standard string) error {
|
|||
}
|
||||
}
|
||||
|
||||
cosignersOffset, data, extErr := cmdargs.GetDataFromContext(ctx)
|
||||
if extErr != nil {
|
||||
return extErr
|
||||
}
|
||||
|
||||
cosigners, extErr := cmdargs.GetSignersFromContext(ctx, cosignersOffset)
|
||||
if extErr != nil {
|
||||
return extErr
|
||||
}
|
||||
signersAccounts, err := cmdargs.GetSignersAccounts(acc, wall, cosigners, transaction.CalledByEntry)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("invalid signers: %w", err), 1)
|
||||
}
|
||||
act, err := actor.New(c, signersAccounts)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to create RPC actor: %w", err), 1)
|
||||
}
|
||||
|
||||
amountArg := ctx.String("amount")
|
||||
amount, err := fixedn.FromString(amountArg, int(token.Decimals))
|
||||
// It's OK for NEP-11 transfer to not have amount set.
|
||||
|
|
2
cli/wallet/testdata/testwallet_NEO3.json
vendored
2
cli/wallet/testdata/testwallet_NEO3.json
vendored
|
@ -52,4 +52,4 @@
|
|||
"extra": {
|
||||
"Tokens": null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,10 +5,13 @@ import (
|
|||
|
||||
"github.com/nspcc-dev/neo-go/cli/cmdargs"
|
||||
"github.com/nspcc-dev/neo-go/cli/flags"
|
||||
"github.com/nspcc-dev/neo-go/cli/input"
|
||||
"github.com/nspcc-dev/neo-go/cli/options"
|
||||
"github.com/nspcc-dev/neo-go/cli/txctx"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/neo"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
|
@ -20,7 +23,7 @@ func newValidatorCommands() []cli.Command {
|
|||
{
|
||||
Name: "register",
|
||||
Usage: "register as a new candidate",
|
||||
UsageText: "register -w <path> -r <rpc> -a <addr> [-g gas] [-e sysgas] [--out file] [--force] [--await]",
|
||||
UsageText: "register -w <path> -r <rpc> -a <addr> [-g gas] [-e sysgas] [--out file] [--force]",
|
||||
Action: handleRegister,
|
||||
Flags: append([]cli.Flag{
|
||||
walletPathFlag,
|
||||
|
@ -29,7 +32,6 @@ func newValidatorCommands() []cli.Command {
|
|||
txctx.SysGasFlag,
|
||||
txctx.OutFlag,
|
||||
txctx.ForceFlag,
|
||||
txctx.AwaitFlag,
|
||||
flags.AddressFlag{
|
||||
Name: "address, a",
|
||||
Usage: "Address to register",
|
||||
|
@ -39,7 +41,7 @@ func newValidatorCommands() []cli.Command {
|
|||
{
|
||||
Name: "unregister",
|
||||
Usage: "unregister self as a candidate",
|
||||
UsageText: "unregister -w <path> -r <rpc> -a <addr> [-g gas] [-e sysgas] [--out file] [--force] [--await]",
|
||||
UsageText: "unregister -w <path> -r <rpc> -a <addr> [-g gas] [-e sysgas] [--out file] [--force]",
|
||||
Action: handleUnregister,
|
||||
Flags: append([]cli.Flag{
|
||||
walletPathFlag,
|
||||
|
@ -48,7 +50,6 @@ func newValidatorCommands() []cli.Command {
|
|||
txctx.SysGasFlag,
|
||||
txctx.OutFlag,
|
||||
txctx.ForceFlag,
|
||||
txctx.AwaitFlag,
|
||||
flags.AddressFlag{
|
||||
Name: "address, a",
|
||||
Usage: "Address to unregister",
|
||||
|
@ -58,10 +59,9 @@ func newValidatorCommands() []cli.Command {
|
|||
{
|
||||
Name: "vote",
|
||||
Usage: "vote for a validator",
|
||||
UsageText: "vote -w <path> -r <rpc> [-s <timeout>] [-g gas] [-e sysgas] -a <addr> [-c <public key>] [--out file] [--force] [--await]",
|
||||
UsageText: "vote -w <path> -r <rpc> [-s <timeout>] [-g gas] [-e sysgas] -a <addr> [-c <public key>] [--out file] [--force]",
|
||||
Description: `Votes for a validator by calling "vote" method of a NEO native
|
||||
contract. Do not provide candidate argument to perform unvoting. If --await flag is
|
||||
included, the command waits for the transaction to be included in a block before exiting.
|
||||
contract. Do not provide candidate argument to perform unvoting.
|
||||
`,
|
||||
Action: handleVote,
|
||||
Flags: append([]cli.Flag{
|
||||
|
@ -71,7 +71,6 @@ func newValidatorCommands() []cli.Command {
|
|||
txctx.SysGasFlag,
|
||||
txctx.OutFlag,
|
||||
txctx.ForceFlag,
|
||||
txctx.AwaitFlag,
|
||||
flags.AddressFlag{
|
||||
Name: "address, a",
|
||||
Usage: "Address to vote from",
|
||||
|
@ -112,7 +111,7 @@ func handleNeoAction(ctx *cli.Context, mkTx func(*neo.Contract, util.Uint160, *w
|
|||
return cli.NewExitError("address was not provided", 1)
|
||||
}
|
||||
addr := addrFlag.Uint160()
|
||||
acc, err := options.GetUnlockedAccount(wall, addr, pass)
|
||||
acc, err := getDecryptedAccount(wall, addr, pass)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
|
@ -120,13 +119,13 @@ func handleNeoAction(ctx *cli.Context, mkTx func(*neo.Contract, util.Uint160, *w
|
|||
gctx, cancel := options.GetTimeoutContext(ctx)
|
||||
defer cancel()
|
||||
|
||||
signers, err := cmdargs.GetSignersAccounts(acc, wall, nil, transaction.CalledByEntry)
|
||||
c, err := options.GetRPCClient(gctx, ctx)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("invalid signers: %w", err), 1)
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
_, act, exitErr := options.GetRPCWithActor(gctx, ctx, signers)
|
||||
if exitErr != nil {
|
||||
return exitErr
|
||||
act, err := actor.NewSimple(c, acc)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("RPC actor issue: %w", err), 1)
|
||||
}
|
||||
|
||||
contract := neo.New(act)
|
||||
|
@ -154,3 +153,32 @@ func handleVote(ctx *cli.Context) error {
|
|||
return contract.VoteUnsigned(addr, pub)
|
||||
})
|
||||
}
|
||||
|
||||
// getDecryptedAccount tries to get and unlock the specified account if it has a
|
||||
// key inside (otherwise it's returned as is, without an ability to sign). If
|
||||
// password is nil, it will be requested via terminal.
|
||||
func getDecryptedAccount(wall *wallet.Wallet, addr util.Uint160, password *string) (*wallet.Account, error) {
|
||||
acc := wall.GetAccount(addr)
|
||||
if acc == nil {
|
||||
return nil, fmt.Errorf("can't find account for the address: %s", address.Uint160ToString(addr))
|
||||
}
|
||||
|
||||
// No private key available, nothing to decrypt, but it's still a useful account for many purposes.
|
||||
if acc.EncryptedWIF == "" {
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
if password == nil {
|
||||
pass, err := input.ReadPassword(EnterPasswordPrompt)
|
||||
if err != nil {
|
||||
fmt.Println("Error reading password", err)
|
||||
return nil, err
|
||||
}
|
||||
password = &pass
|
||||
}
|
||||
err := acc.Decrypt(*password, wall.Scrypt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return acc, nil
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/cli/input"
|
||||
"github.com/nspcc-dev/neo-go/cli/options"
|
||||
"github.com/nspcc-dev/neo-go/cli/txctx"
|
||||
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||
|
@ -25,6 +26,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
"github.com/urfave/cli"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -86,7 +88,6 @@ func NewCommands() []cli.Command {
|
|||
txctx.SysGasFlag,
|
||||
txctx.OutFlag,
|
||||
txctx.ForceFlag,
|
||||
txctx.AwaitFlag,
|
||||
flags.AddressFlag{
|
||||
Name: "address, a",
|
||||
Usage: "Address to claim GAS for",
|
||||
|
@ -97,7 +98,6 @@ func NewCommands() []cli.Command {
|
|||
walletPathFlag,
|
||||
walletConfigFlag,
|
||||
txctx.OutFlag,
|
||||
txctx.AwaitFlag,
|
||||
inFlag,
|
||||
flags.AddressFlag{
|
||||
Name: "address, a",
|
||||
|
@ -112,7 +112,7 @@ func NewCommands() []cli.Command {
|
|||
{
|
||||
Name: "claim",
|
||||
Usage: "claim GAS",
|
||||
UsageText: "neo-go wallet claim -w wallet [--wallet-config path] [-g gas] [-e sysgas] -a address -r endpoint [-s timeout] [--out file] [--force] [--await]",
|
||||
UsageText: "neo-go wallet claim -w wallet [--wallet-config path] [-g gas] [-e sysgas] -a address -r endpoint [-s timeout] [--out file] [--force]",
|
||||
Action: claimGas,
|
||||
Flags: claimFlags,
|
||||
},
|
||||
|
@ -236,15 +236,8 @@ func NewCommands() []cli.Command {
|
|||
{
|
||||
Name: "import-multisig",
|
||||
Usage: "import multisig contract",
|
||||
UsageText: "import-multisig -w wallet [--wallet-config path] [--wif <wif>] [--name <account_name>] --min <m>" +
|
||||
UsageText: "import-multisig -w wallet [--wallet-config path] --wif <wif> [--name <account_name>] --min <n>" +
|
||||
" [<pubkey1> [<pubkey2> [...]]]",
|
||||
Description: `Imports a standard multisignature contract with "m out of n" signatures required where "m" is
|
||||
specified by --min flag and "n" is the length of provided set of public keys. If
|
||||
--wif flag is provided, it's used to create an account with the given name (or
|
||||
without a name if --name flag is not provided). Otherwise, the command tries to
|
||||
find an account with one of the given public keys and convert it to multisig. If
|
||||
no suitable account is found and no --wif flag is specified, an error is returned.
|
||||
`,
|
||||
Action: importMultisig,
|
||||
Flags: []cli.Flag{
|
||||
walletPathFlag,
|
||||
|
@ -297,15 +290,13 @@ func NewCommands() []cli.Command {
|
|||
{
|
||||
Name: "sign",
|
||||
Usage: "cosign transaction with multisig/contract/additional account",
|
||||
UsageText: "sign -w wallet [--wallet-config path] --address <address> --in <file.in> [--out <file.out>] [-r <endpoint>] [--await]",
|
||||
UsageText: "sign -w wallet [--wallet-config path] --address <address> --in <file.in> [--out <file.out>] [-r <endpoint>]",
|
||||
Description: `Signs the given (in file.in) context (which must be a transaction
|
||||
signing context) for the given address using the given wallet. This command can
|
||||
output the resulting JSON (with additional signature added) right to the console
|
||||
(if no file.out and no RPC endpoint specified) or into a file (which can be the
|
||||
same as input one). If an RPC endpoint is given it'll also try to construct a
|
||||
complete transaction and send it via RPC (printing its hash if everything is OK).
|
||||
If the --await (with a given RPC endpoint) flag is included, the command waits
|
||||
for the transaction to be included in a block before exiting.
|
||||
complete transaction and send it via RPC (printing its hash if everything is OK).
|
||||
`,
|
||||
Action: signStoredTransaction,
|
||||
Flags: signFlags,
|
||||
|
@ -528,12 +519,6 @@ loop:
|
|||
}
|
||||
|
||||
func importMultisig(ctx *cli.Context) error {
|
||||
var (
|
||||
label *string
|
||||
acc *wallet.Account
|
||||
accPub *keys.PublicKey
|
||||
)
|
||||
|
||||
wall, pass, err := openWallet(ctx, true)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
|
@ -555,45 +540,12 @@ func importMultisig(ctx *cli.Context) error {
|
|||
}
|
||||
}
|
||||
|
||||
var label *string
|
||||
if ctx.IsSet("name") {
|
||||
l := ctx.String("name")
|
||||
label = &l
|
||||
}
|
||||
|
||||
loop:
|
||||
for _, pub := range pubs {
|
||||
for _, wallAcc := range wall.Accounts {
|
||||
if wallAcc.ScriptHash().Equals(pub.GetScriptHash()) {
|
||||
if acc != nil {
|
||||
// Multiple matching accounts found, fallback to WIF-based conversion.
|
||||
acc = nil
|
||||
break loop
|
||||
}
|
||||
acc = new(wallet.Account)
|
||||
*acc = *wallAcc
|
||||
accPub = pub
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if acc != nil {
|
||||
err = acc.ConvertMultisigEncrypted(accPub, m, pubs)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
if label != nil {
|
||||
acc.Label = *label
|
||||
}
|
||||
if err := addAccountAndSave(wall, acc); err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if !ctx.IsSet("wif") {
|
||||
return cli.NewExitError(errors.New("none of the provided public keys correspond to an existing key in the wallet or multiple matching accounts found in the wallet, and no WIF is provided"), 1)
|
||||
}
|
||||
acc, err = newAccountFromWIF(ctx.App.Writer, ctx.String("wif"), wall.Scrypt, label, pass)
|
||||
acc, err := newAccountFromWIF(ctx.App.Writer, ctx.String("wif"), wall.Scrypt, label, pass)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
|
@ -651,8 +603,7 @@ func importDeployed(ctx *cli.Context) error {
|
|||
return cli.NewExitError("contract has no `verify` method with boolean return", 1)
|
||||
}
|
||||
acc.Address = address.Uint160ToString(cs.Hash)
|
||||
// Explicitly overwrite single signature script of the provided WIF since the contract is known to be deployed.
|
||||
acc.Contract.Script = nil
|
||||
acc.Contract.Script = cs.NEF.Script
|
||||
acc.Contract.Parameters = acc.Contract.Parameters[:0]
|
||||
for _, p := range md.Parameters {
|
||||
acc.Contract.Parameters = append(acc.Contract.Parameters, wallet.ContractParam{
|
||||
|
@ -871,7 +822,7 @@ func createWallet(ctx *cli.Context) error {
|
|||
}
|
||||
var pass *string
|
||||
if len(configPath) != 0 {
|
||||
cfg, err := options.ReadWalletConfig(configPath)
|
||||
cfg, err := ReadWalletConfig(configPath)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
|
@ -949,14 +900,14 @@ func createAccount(wall *wallet.Wallet, pass *string) error {
|
|||
func openWallet(ctx *cli.Context, canUseWalletConfig bool) (*wallet.Wallet, *string, error) {
|
||||
path, pass, err := getWalletPathAndPass(ctx, canUseWalletConfig)
|
||||
if err != nil {
|
||||
return nil, nil, cli.NewExitError(fmt.Errorf("failed to get wallet path or password: %w", err), 1)
|
||||
return nil, nil, err
|
||||
}
|
||||
if path == "-" {
|
||||
return nil, nil, errNoStdin
|
||||
}
|
||||
w, err := wallet.NewWalletFromFile(path)
|
||||
if err != nil {
|
||||
return nil, nil, cli.NewExitError(fmt.Errorf("failed to read wallet: %w", err), 1)
|
||||
return nil, nil, err
|
||||
}
|
||||
return w, pass, nil
|
||||
}
|
||||
|
@ -995,7 +946,7 @@ func getWalletPathAndPass(ctx *cli.Context, canUseWalletConfig bool) (string, *s
|
|||
}
|
||||
var pass *string
|
||||
if len(configPath) != 0 {
|
||||
cfg, err := options.ReadWalletConfig(configPath)
|
||||
cfg, err := ReadWalletConfig(configPath)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
@ -1005,6 +956,27 @@ func getWalletPathAndPass(ctx *cli.Context, canUseWalletConfig bool) (string, *s
|
|||
return path, pass, nil
|
||||
}
|
||||
|
||||
func ReadWalletConfig(configPath string) (*config.Wallet, error) {
|
||||
file, err := os.Open(configPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
configData, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to read wallet config: %w", err)
|
||||
}
|
||||
|
||||
cfg := &config.Wallet{}
|
||||
|
||||
err = yaml.Unmarshal(configData, &cfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal wallet config YAML: %w", err)
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func newAccountFromWIF(w io.Writer, wif string, scrypt keys.ScryptParams, label *string, pass *string) (*wallet.Account, error) {
|
||||
var (
|
||||
phrase, name string
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package wallet_test
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -436,16 +437,16 @@ func TestWalletInit(t *testing.T) {
|
|||
"--wallet", walletPath,
|
||||
"--min", "2"}
|
||||
t.Run("invalid pub encoding", func(t *testing.T) {
|
||||
e.RunWithError(t, append(cmd, pubs[1].StringCompressed(),
|
||||
pubs[1].StringCompressed(),
|
||||
pubs[2].StringCompressed(),
|
||||
e.RunWithError(t, append(cmd, hex.EncodeToString(pubs[1].Bytes()),
|
||||
hex.EncodeToString(pubs[1].Bytes()),
|
||||
hex.EncodeToString(pubs[2].Bytes()),
|
||||
"not-a-pub")...)
|
||||
})
|
||||
t.Run("missing WIF", func(t *testing.T) {
|
||||
e.RunWithError(t, append(cmd, pubs[0].StringCompressed(),
|
||||
pubs[1].StringCompressed(),
|
||||
pubs[2].StringCompressed(),
|
||||
pubs[3].StringCompressed())...)
|
||||
e.RunWithError(t, append(cmd, hex.EncodeToString(pubs[0].Bytes()),
|
||||
hex.EncodeToString(pubs[1].Bytes()),
|
||||
hex.EncodeToString(pubs[2].Bytes()),
|
||||
hex.EncodeToString(pubs[3].Bytes()))...)
|
||||
})
|
||||
cmd = append(cmd, "--wif", privs[0].WIF())
|
||||
t.Run("InvalidPublicKeys", func(t *testing.T) {
|
||||
|
@ -454,18 +455,18 @@ func TestWalletInit(t *testing.T) {
|
|||
e.In.WriteString("multipass\r")
|
||||
defer e.In.Reset()
|
||||
|
||||
e.RunWithError(t, append(cmd, pubs[1].StringCompressed(),
|
||||
pubs[1].StringCompressed(),
|
||||
pubs[2].StringCompressed(),
|
||||
pubs[3].StringCompressed())...)
|
||||
e.RunWithError(t, append(cmd, hex.EncodeToString(pubs[1].Bytes()),
|
||||
hex.EncodeToString(pubs[1].Bytes()),
|
||||
hex.EncodeToString(pubs[2].Bytes()),
|
||||
hex.EncodeToString(pubs[3].Bytes()))...)
|
||||
})
|
||||
e.In.WriteString("multiacc\r")
|
||||
e.In.WriteString("multipass\r")
|
||||
e.In.WriteString("multipass\r")
|
||||
e.Run(t, append(cmd, pubs[0].StringCompressed(),
|
||||
pubs[1].StringCompressed(),
|
||||
pubs[2].StringCompressed(),
|
||||
pubs[3].StringCompressed())...)
|
||||
e.Run(t, append(cmd, hex.EncodeToString(pubs[0].Bytes()),
|
||||
hex.EncodeToString(pubs[1].Bytes()),
|
||||
hex.EncodeToString(pubs[2].Bytes()),
|
||||
hex.EncodeToString(pubs[3].Bytes()))...)
|
||||
|
||||
script, err := smartcontract.CreateMultiSigRedeemScript(2, pubs)
|
||||
require.NoError(t, err)
|
||||
|
@ -481,62 +482,10 @@ func TestWalletInit(t *testing.T) {
|
|||
e.In.WriteString("multiacc\r")
|
||||
e.In.WriteString("multipass\r")
|
||||
e.In.WriteString("multipass\r")
|
||||
e.RunWithError(t, append(cmd, pubs[0].StringCompressed(),
|
||||
pubs[1].StringCompressed(),
|
||||
pubs[2].StringCompressed(),
|
||||
pubs[3].StringCompressed())...)
|
||||
})
|
||||
|
||||
privs, pubs = testcli.GenerateKeys(t, 3)
|
||||
script, err = smartcontract.CreateMultiSigRedeemScript(2, pubs)
|
||||
require.NoError(t, err)
|
||||
// Create a wallet and import a standard account
|
||||
e.Run(t, "neo-go", "wallet", "init", "--wallet", walletPath)
|
||||
e.In.WriteString("standardacc\rstdpass\rstdpass\r")
|
||||
e.Run(t, "neo-go", "wallet", "import",
|
||||
"--wallet", walletPath,
|
||||
"--wif", privs[0].WIF())
|
||||
w, err = wallet.NewWalletFromFile(walletPath)
|
||||
require.NoError(t, err)
|
||||
actual = w.GetAccount(privs[0].GetScriptHash())
|
||||
require.NotNil(t, actual)
|
||||
require.NotEqual(t, actual.Contract.Script, script)
|
||||
|
||||
// Test when a public key of an already imported account is present
|
||||
t.Run("existing account public key, no WIF", func(t *testing.T) {
|
||||
e.Run(t, "neo-go", "wallet", "import-multisig",
|
||||
"--wallet", walletPath,
|
||||
"--min", "2",
|
||||
pubs[0].StringCompressed(), // Public key of the already imported account
|
||||
pubs[1].StringCompressed(),
|
||||
pubs[2].StringCompressed())
|
||||
|
||||
w, err := wallet.NewWalletFromFile(walletPath)
|
||||
require.NoError(t, err)
|
||||
actual := w.GetAccount(hash.Hash160(script))
|
||||
require.NotNil(t, actual)
|
||||
require.Equal(t, actual.Contract.Script, script)
|
||||
require.NoError(t, actual.Decrypt("stdpass", w.Scrypt))
|
||||
require.NotEqual(t, actual.Address, w.GetAccount(privs[0].GetScriptHash()).Address)
|
||||
})
|
||||
|
||||
// Test when no public key of an already imported account is present, and no WIF is provided
|
||||
t.Run("no existing account public key, no WIF", func(t *testing.T) {
|
||||
_, pubsNew := testcli.GenerateKeys(t, 3)
|
||||
scriptNew, err := smartcontract.CreateMultiSigRedeemScript(2, pubsNew)
|
||||
require.NoError(t, err)
|
||||
|
||||
e.RunWithError(t, "neo-go", "wallet", "import-multisig",
|
||||
"--wallet", walletPath,
|
||||
"--min", "2",
|
||||
pubsNew[0].StringCompressed(),
|
||||
pubsNew[1].StringCompressed(),
|
||||
pubsNew[2].StringCompressed())
|
||||
|
||||
w, err := wallet.NewWalletFromFile(walletPath)
|
||||
require.NoError(t, err)
|
||||
actual := w.GetAccount(hash.Hash160(scriptNew))
|
||||
require.Nil(t, actual)
|
||||
e.RunWithError(t, append(cmd, hex.EncodeToString(pubs[0].Bytes()),
|
||||
hex.EncodeToString(pubs[1].Bytes()),
|
||||
hex.EncodeToString(pubs[2].Bytes()),
|
||||
hex.EncodeToString(pubs[3].Bytes()))...)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -656,47 +605,6 @@ func TestWalletClaimGas(t *testing.T) {
|
|||
} else {
|
||||
require.Equal(t, 1, balanceAfter.Cmp(balanceBefore))
|
||||
}
|
||||
t.Run("await", func(t *testing.T) {
|
||||
args := []string{
|
||||
"neo-go", "wallet", "nep17", "multitransfer",
|
||||
"--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
|
||||
"--wallet", testcli.ValidatorWallet,
|
||||
"--from", testcli.ValidatorAddr, "--await",
|
||||
"--force",
|
||||
"NEO:" + testcli.TestWalletAccount + ":1000",
|
||||
"GAS:" + testcli.TestWalletAccount + ":1000", // for tx send
|
||||
}
|
||||
e.In.WriteString("one\r")
|
||||
e.Run(t, args...)
|
||||
e.CheckAwaitableTxPersisted(t)
|
||||
|
||||
h, err := address.StringToUint160(testcli.TestWalletAccount)
|
||||
require.NoError(t, err)
|
||||
|
||||
balanceBefore := e.Chain.GetUtilityTokenBalance(h)
|
||||
claimHeight := e.Chain.BlockHeight() + 1
|
||||
cl, err := e.Chain.CalculateClaimable(h, claimHeight)
|
||||
require.NoError(t, err)
|
||||
require.True(t, cl.Sign() > 0)
|
||||
|
||||
e.In.WriteString("testpass\r")
|
||||
e.Run(t, "neo-go", "wallet", "claim",
|
||||
"--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
|
||||
"--wallet", testcli.TestWalletPath,
|
||||
"--address", testcli.TestWalletAccount,
|
||||
"--force", "--await")
|
||||
tx, height = e.CheckAwaitableTxPersisted(t)
|
||||
balanceBefore.Sub(balanceBefore, big.NewInt(tx.NetworkFee+tx.SystemFee))
|
||||
balanceBefore.Add(balanceBefore, cl)
|
||||
|
||||
balanceAfter = e.Chain.GetUtilityTokenBalance(h)
|
||||
// height can be bigger than claimHeight especially when tests are executed with -race.
|
||||
if height == claimHeight {
|
||||
require.Equal(t, 0, balanceAfter.Cmp(balanceBefore))
|
||||
} else {
|
||||
require.Equal(t, 1, balanceAfter.Cmp(balanceBefore))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestWalletImportDeployed(t *testing.T) {
|
||||
|
@ -914,31 +822,6 @@ func TestOfflineSigning(t *testing.T) {
|
|||
"--in", txPath)
|
||||
})
|
||||
e.CheckTxPersisted(t)
|
||||
|
||||
t.Run("await 1/1 multisig", func(t *testing.T) {
|
||||
args := []string{"neo-go", "wallet", "nep17", "transfer",
|
||||
"--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
|
||||
"--wallet", walletPath,
|
||||
"--from", testcli.ValidatorAddr,
|
||||
"--to", w.Accounts[0].Address,
|
||||
"--token", "NEO",
|
||||
"--amount", "1",
|
||||
"--force",
|
||||
}
|
||||
e.Run(t, append(args, "--out", txPath)...)
|
||||
|
||||
e.In.WriteString("one\r")
|
||||
e.Run(t, "neo-go", "wallet", "sign",
|
||||
"--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr,
|
||||
"--in", txPath, "--out", txPath)
|
||||
|
||||
e.Run(t, "neo-go", "wallet", "sign",
|
||||
"--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
|
||||
"--wallet", walletPath, "--address", testcli.ValidatorAddr,
|
||||
"--in", txPath, "--await")
|
||||
e.CheckAwaitableTxPersisted(t)
|
||||
})
|
||||
|
||||
t.Run("simple signature", func(t *testing.T) {
|
||||
simpleAddr := w.Accounts[0].Address
|
||||
args := []string{"neo-go", "wallet", "nep17", "transfer",
|
||||
|
@ -970,31 +853,6 @@ func TestOfflineSigning(t *testing.T) {
|
|||
"--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
|
||||
txPath)
|
||||
})
|
||||
|
||||
t.Run("await simple signature", func(t *testing.T) {
|
||||
simpleAddr := w.Accounts[0].Address
|
||||
args := []string{"neo-go", "wallet", "nep17", "transfer",
|
||||
"--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
|
||||
"--wallet", walletPath,
|
||||
"--from", simpleAddr,
|
||||
"--to", testcli.ValidatorAddr,
|
||||
"--token", "NEO",
|
||||
"--amount", "1",
|
||||
"--force",
|
||||
}
|
||||
|
||||
e.Run(t, append(args, "--out", txPath)...)
|
||||
|
||||
e.In.WriteString("one\r")
|
||||
e.Run(t, "neo-go", "wallet", "sign",
|
||||
"--wallet", testcli.ValidatorWallet, "--address", simpleAddr,
|
||||
"--in", txPath, "--out", txPath)
|
||||
|
||||
e.Run(t, "neo-go", "util", "sendtx",
|
||||
"--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
|
||||
txPath, "--await")
|
||||
e.CheckAwaitableTxPersisted(t)
|
||||
})
|
||||
}
|
||||
|
||||
func TestWalletDump(t *testing.T) {
|
||||
|
|
|
@ -26,7 +26,6 @@ ProtocolConfiguration:
|
|||
Hardforks:
|
||||
Aspidochelone: 3000000
|
||||
Basilisk: 4500000
|
||||
Cockatrice: 5800000
|
||||
|
||||
ApplicationConfiguration:
|
||||
SkipBlockVerification: false
|
||||
|
|
|
@ -38,7 +38,6 @@ ProtocolConfiguration:
|
|||
Hardforks:
|
||||
Aspidochelone: 1730000
|
||||
Basilisk: 4120000
|
||||
Cockatrice: 5450000
|
||||
|
||||
ApplicationConfiguration:
|
||||
SkipBlockVerification: false
|
||||
|
|
|
@ -41,7 +41,6 @@ ProtocolConfiguration:
|
|||
Hardforks:
|
||||
Aspidochelone: 210000
|
||||
Basilisk: 2680000
|
||||
Cockatrice: 3967000
|
||||
|
||||
ApplicationConfiguration:
|
||||
SkipBlockVerification: false
|
||||
|
|
|
@ -38,6 +38,11 @@ ApplicationConfiguration:
|
|||
UnlockWallet:
|
||||
Path: "../testdata/wallet1_solo.json"
|
||||
Password: "one"
|
||||
P2PNotary:
|
||||
Enabled: false
|
||||
UnlockWallet:
|
||||
Path: "/notary_wallet.json"
|
||||
Password: "pass"
|
||||
RPC:
|
||||
MaxGasInvoke: 15
|
||||
Enabled: true
|
||||
|
|
|
@ -42,6 +42,11 @@ ApplicationConfiguration:
|
|||
AttemptConnPeers: 5
|
||||
MinPeers: 0
|
||||
Relay: true
|
||||
P2PNotary:
|
||||
Enabled: false
|
||||
UnlockWallet:
|
||||
Path: "/notary_wallet.json"
|
||||
Password: "pass"
|
||||
RPC:
|
||||
MaxGasInvoke: 15
|
||||
Enabled: true
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
# Project-specific labels
|
||||
|
||||
## Component
|
||||
|
||||
There is a number of internal components:
|
||||
|
||||
- cli
|
||||
- compiler
|
||||
- consensus
|
||||
- network
|
||||
- oracle
|
||||
- rpc
|
||||
- smartcontract
|
||||
- vm
|
||||
- wallet
|
||||
|
||||
## Platform
|
||||
|
||||
In general we support Linux, Mac and Windows, but currently we use this:
|
||||
|
||||
- windows
|
||||
|
||||
It caused so many problems that it deserves a label of its own.
|
|
@ -332,7 +332,7 @@ protocol-related settings described in the table below.
|
|||
| --- | --- | --- | --- | --- |
|
||||
| CommitteeHistory | map[uint32]uint32 | none | Number of committee members after the given height, for example `{0: 1, 20: 4}` sets up a chain with one committee member since the genesis and then changes the setting to 4 committee members at the height of 20. `StandbyCommittee` committee setting must have the number of keys equal or exceeding the highest value in this option. Blocks numbers where the change happens must be divisible by the old and by the new values simultaneously. If not set, committee size is derived from the `StandbyCommittee` setting and never changes. |
|
||||
| Genesis | [Genesis](#Genesis-Configuration) | none | The set of genesis block settings including NeoGo-specific protocol extensions that should be enabled at the genesis block or during native contracts initialisation. |
|
||||
| Hardforks | `map[string]uint32` | [] | The set of incompatible changes that affect node behaviour starting from the specified height. The default value is an empty set which should be interpreted as "each known hard-fork is applied from the zero blockchain height". The list of valid hard-fork names:<br>• `Aspidochelone` represents hard-fork introduced in [#2469](https://github.com/nspcc-dev/neo-go/pull/2469) (ported from the [reference](https://github.com/neo-project/neo/pull/2712)). It adjusts the prices of `System.Contract.CreateStandardAccount` and `System.Contract.CreateMultisigAccount` interops so that the resulting prices are in accordance with `sha256` method of native `CryptoLib` contract. It also includes [#2519](https://github.com/nspcc-dev/neo-go/pull/2519) (ported from the [reference](https://github.com/neo-project/neo/pull/2749)) that adjusts the price of `System.Runtime.GetRandom` interop and fixes its vulnerability. A special NeoGo-specific change is included as well for ContractManagement's update/deploy call flags behaviour to be compatible with pre-0.99.0 behaviour that was changed because of the [3.2.0 protocol change](https://github.com/neo-project/neo/pull/2653).<br>• `Basilisk` represents hard-fork introduced in [#3056](https://github.com/nspcc-dev/neo-go/pull/3056) (ported from the [reference](https://github.com/neo-project/neo/pull/2881)). It enables strict smart contract script check against a set of JMP instructions and against method boundaries enabled on contract deploy or update. It also includes [#3080](https://github.com/nspcc-dev/neo-go/pull/3080) (ported from the [reference](https://github.com/neo-project/neo/pull/2883)) that increases `stackitem.Integer` JSON parsing precision up to the maximum value supported by the NeoVM. It also includes [#3085](https://github.com/nspcc-dev/neo-go/pull/3085) (ported from the [reference](https://github.com/neo-project/neo/pull/2810)) that enables strict check for notifications emitted by a contract to precisely match the events specified in the contract manifest. <br>• `Cockatrice` represents hard-fork introduced in [#3402](https://github.com/nspcc-dev/neo-go/pull/3402) (ported from the [reference](https://github.com/neo-project/neo/pull/2942)). Initially it is introduced along with the ability to update native contracts. This hard-fork also includes a couple of new native smart contract APIs: `keccak256` of native CryptoLib contract introduced in [#3301](https://github.com/nspcc-dev/neo-go/pull/3301) (ported from the [reference](https://github.com/neo-project/neo/pull/2925)) and `getCommitteeAddress` of native NeoToken contract inctroduced in [#3362](https://github.com/nspcc-dev/neo-go/pull/3362) (ported from the [reference](https://github.com/neo-project/neo/pull/3154)). |
|
||||
| Hardforks | `map[string]uint32` | [] | The set of incompatible changes that affect node behaviour starting from the specified height. The default value is an empty set which should be interpreted as "each known hard-fork is applied from the zero blockchain height". The list of valid hard-fork names:<br>• `Aspidochelone` represents hard-fork introduced in [#2469](https://github.com/nspcc-dev/neo-go/pull/2469) (ported from the [reference](https://github.com/neo-project/neo/pull/2712)). It adjusts the prices of `System.Contract.CreateStandardAccount` and `System.Contract.CreateMultisigAccount` interops so that the resulting prices are in accordance with `sha256` method of native `CryptoLib` contract. It also includes [#2519](https://github.com/nspcc-dev/neo-go/pull/2519) (ported from the [reference](https://github.com/neo-project/neo/pull/2749)) that adjusts the price of `System.Runtime.GetRandom` interop and fixes its vulnerability. A special NeoGo-specific change is included as well for ContractManagement's update/deploy call flags behaviour to be compatible with pre-0.99.0 behaviour that was changed because of the [3.2.0 protocol change](https://github.com/neo-project/neo/pull/2653).<br>• `Basilisk` represents hard-fork introduced in [#3056](https://github.com/nspcc-dev/neo-go/pull/3056) (ported from the [reference](https://github.com/neo-project/neo/pull/2881)). It enables strict smart contract script check against a set of JMP instructions and against method boundaries enabled on contract deploy or update. It also includes [#3080](https://github.com/nspcc-dev/neo-go/pull/3080) (ported from the [reference](https://github.com/neo-project/neo/pull/2883)) that increases `stackitem.Integer` JSON parsing precision up to the maximum value supported by the NeoVM. It also includes [#3085](https://github.com/nspcc-dev/neo-go/pull/3085) (ported from the [reference](https://github.com/neo-project/neo/pull/2810)) that enables strict check for notifications emitted by a contract to precisely match the events specified in the contract manifest. |
|
||||
| Magic | `uint32` | `0` | Magic number which uniquely identifies Neo network. |
|
||||
| MaxBlockSize | `uint32` | `262144` | Maximum block size in bytes. |
|
||||
| MaxBlockSystemFee | `int64` | `900000000000` | Maximum overall transactions system fee per block. |
|
||||
|
@ -345,7 +345,7 @@ protocol-related settings described in the table below.
|
|||
| P2PStateExchangeExtensions | `bool` | `false` | Enables the following P2P MPT state data exchange logic: <br>• `StateSyncInterval` protocol setting <br>• P2P commands `GetMPTDataCMD` and `MPTDataCMD` | Not supported by the C# node, thus may affect heterogeneous networks functionality. Can be supported either on MPT-complete node (`KeepOnlyLatestState`=`false`) or on light GC-enabled node (`RemoveUntraceableBlocks=true`) in which case `KeepOnlyLatestState` setting doesn't change the behavior, an appropriate set of MPTs is always stored (see `RemoveUntraceableBlocks`). |
|
||||
| ReservedAttributes | `bool` | `false` | Allows to have reserved attributes range for experimental or private purposes. |
|
||||
| SeedList | `[]string` | [] | List of initial nodes addresses used to establish connectivity. |
|
||||
| StandbyCommittee | `[]string` | [] | List of public keys of standby committee validators are chosen from. | The list of keys is not required to be sorted, but it must be exactly the same within the configuration files of all the nodes in the network. |
|
||||
| StandbyCommittee | `[]string` | [] | List of public keys of standby committee validators are chosen from. |
|
||||
| StateRootInHeader | `bool` | `false` | Enables storing state root in block header. | Experimental protocol extension! |
|
||||
| StateSyncInterval | `int` | `40000` | The number of blocks between state heights available for MPT state data synchronization. | `P2PStateExchangeExtensions` should be enabled to use this setting. |
|
||||
| TimePerBlock | `Duration` | `15s` | Minimal (and targeted for) time interval between blocks. Must be an integer number of milliseconds. |
|
||||
|
|
|
@ -388,7 +388,7 @@ subpackage with an example written in Go doc.
|
|||
configuration (just a simple `RET` script by default), pack both transactions
|
||||
into a P2PNotaryRequest and submit it to the RPC node. It returns hashes of
|
||||
the main and fallback transactions as well as their `ValidUntilBlock` value.
|
||||
If you need more control over fallback transaction use `Actor` options or
|
||||
If you need more control over fallback transction use `Actor` options or
|
||||
[func (*Actor) SendRequest](https://pkg.go.dev/github.com/nspcc-dev/neo-go/pkg/rpcclient/notary#Actor.SendRequest)
|
||||
API.
|
||||
|
||||
|
|
|
@ -27,27 +27,20 @@ Currently supported events:
|
|||
Filters use conjunctional logic.
|
||||
|
||||
## Ordering and persistence guarantees
|
||||
* new block and header of this block are only announced after block's processing
|
||||
is complete and the chain is updated to the new height
|
||||
* new block is only announced after its processing is complete and the chain
|
||||
is updated to the new height
|
||||
* no disk-level persistence guarantees are given
|
||||
* header of newly added block is announced after block processing, but before
|
||||
announcing the block itself
|
||||
* new in-block transaction is announced after block processing, but before
|
||||
announcing the block header and the block itself
|
||||
announcing the block itself
|
||||
* transaction notifications are only announced for successful transactions
|
||||
* all announcements are being done in the same order they happen on the chain.
|
||||
* all announcements are being done in the same order they happen on the chain
|
||||
First, OnPersist script execution is announced followed by notifications generated
|
||||
during the script execution. After that transaction execution is announced. It is
|
||||
then followed by notifications generated during this execution. Next, follows the
|
||||
transaction announcement. Transaction announcements are ordered the same way
|
||||
they're in the block. After all in-block transactions announcements PostPersist
|
||||
script execution is announced followed by notifications generated during the
|
||||
script execution. Finally, block header is announced followed by the block
|
||||
announcement itself.
|
||||
* notary request events announcements are not bound to the chain processing.
|
||||
Trigger for notary request notifications is notary request mempool content
|
||||
change, thus, notary request event is announced every time notary request
|
||||
enters or leaves notary pool.
|
||||
script execution. Finally, block announcement is followed.
|
||||
* unsubscription may not cancel pending, but not yet sent events
|
||||
|
||||
## Subscription management
|
||||
|
@ -67,17 +60,11 @@ omitted if empty).
|
|||
|
||||
Recognized stream names:
|
||||
* `block_added`
|
||||
Filter: `primary` as an integer with a valid range of 0-255 with
|
||||
primary (speaker) node index from ConsensusData and/or `since` field as
|
||||
an integer value with block index starting from which new block
|
||||
notifications will be received and/or `till` field as an integer values
|
||||
containing block index till which new block notifications will be received.
|
||||
* `header_of_added_block`
|
||||
Filter: `primary` as an integer with primary (speaker) node index from
|
||||
ConsensusData and/or `since` field as an integer value with header
|
||||
index starting from which new header notifications will be received and/or
|
||||
`till` field as an integer values containing header index till which new
|
||||
header notifications will be received.
|
||||
ConsensusData and/or `since` field as an integer value with block
|
||||
index starting from which new block notifications will be received and/or
|
||||
`till` field as an integer values containing block index till which new
|
||||
block notifications will be received.
|
||||
* `transaction_added`
|
||||
Filter: `sender` field containing a string with hex-encoded Uint160 (LE
|
||||
representation) for transaction's `Sender` and/or `signer` in the same
|
||||
|
@ -85,8 +72,7 @@ Recognized stream names:
|
|||
* `notification_from_execution`
|
||||
Filter: `contract` field containing a string with hex-encoded Uint160 (LE
|
||||
representation) and/or `name` field containing a string with execution
|
||||
notification name which should be a valid UTF-8 string not longer than
|
||||
32 bytes.
|
||||
notification name.
|
||||
* `transaction_executed`
|
||||
Filter: `state` field containing `HALT` or `FAULT` string for successful
|
||||
and failed executions respectively and/or `container` field containing
|
||||
|
@ -94,8 +80,7 @@ Recognized stream names:
|
|||
* `notary_request_event`
|
||||
Filter: `sender` field containing a string with hex-encoded Uint160 (LE
|
||||
representation) for notary request's `Sender` and/or `signer` in the same
|
||||
format for one of main transaction's `Signers`. `type` field containing a
|
||||
string with event type, which could be one of "added" or "removed".
|
||||
format for one of main transaction's `Signers`.
|
||||
|
||||
Response: returns subscription ID (string) as a result. This ID can be used to
|
||||
cancel this subscription and has no meaning other than that.
|
||||
|
@ -260,47 +245,6 @@ Example:
|
|||
}
|
||||
```
|
||||
|
||||
### `header_of_added_block` notification
|
||||
|
||||
The first parameter (`params` section) contains a header of added block
|
||||
converted to a JSON structure, which is similar to a verbose
|
||||
`getblockheader` response but with the following differences:
|
||||
* it doesn't have `size` field (you can calculate it client-side)
|
||||
* it doesn't have `nextblockhash` field (it's supposed to be the latest
|
||||
one anyway)
|
||||
* it doesn't have `confirmations` field (see previous)
|
||||
|
||||
No other parameters are sent.
|
||||
|
||||
Example:
|
||||
```
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "header_of_added_block",
|
||||
"params": [
|
||||
{
|
||||
"index" : 207,
|
||||
"time" : 1590006200,
|
||||
"nextconsensus" : "AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL",
|
||||
"consensusdata" : {
|
||||
"primary" : 0,
|
||||
"nonce" : "0000000000000457"
|
||||
},
|
||||
"previousblockhash" : "0x04f7580b111ec75f0ce68d3a9fd70a0544b4521b4a98541694d8575c548b759e",
|
||||
"witnesses" : [
|
||||
{
|
||||
"invocation" : "0c4063429fca5ff75c964d9e38179c75978e33f8174d91a780c2e825265cf2447281594afdd5f3e216dcaf5ff0693aec83f415996cf224454495495f6bd0a4c5d08f0c4099680903a954278580d8533121c2cd3e53a089817b6a784901ec06178a60b5f1da6e70422bdcadc89029767e08d66ce4180b99334cb2d42f42e4216394af15920c4067d5e362189e48839a24e187c59d46f5d9db862c8a029777f1548b19632bfdc73ad373827ed02369f925e89c2303b64e6b9838dca229949b9b9d3bd4c0c3ed8f0c4021d4c00d4522805883f1db929554441bcbbee127c48f6b7feeeb69a72a78c7f0a75011663e239c0820ef903f36168f42936de10f0ef20681cb735a4b53d0390f",
|
||||
"verification" : "130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb"
|
||||
}
|
||||
],
|
||||
"version" : 0,
|
||||
"hash" : "0x239fea00c54c2f6812612874183b72bef4473fcdf68bf8da08d74fd5b6cab030",
|
||||
"merkleroot" : "0xb2c7230ebee4cb83bc03afadbba413e6bca8fcdeaf9c077bea060918da0e52a1"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### `transaction_added` notification
|
||||
|
||||
The first parameter (`params` section) contains a transaction converted to
|
||||
|
|
|
@ -10,8 +10,7 @@ These should run successfully:
|
|||
* unit-tests
|
||||
* lint
|
||||
* privnet with consensus nodes
|
||||
* testnet and mainnet synchronization
|
||||
* NeoFS testnet and mainnet synchronisation and containers compatibility tests
|
||||
* mainnet synchronization
|
||||
|
||||
## Update CHANGELOG and ROADMAP
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
module github.com/nspcc-dev/neo-go/examples/engine
|
||||
|
||||
go 1.20
|
||||
go 1.19
|
||||
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d h1:Vcb7YkZuUSSIC+WF/xV3UDfHbAxZgyT2zGleJP3Ig5k=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d/go.mod h1:/vrbWSHc7YS1KSYhVOyyeucXW/e+1DkVBOgnBEXUCeY=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
module github.com/nspcc-dev/neo-go/examples/events
|
||||
|
||||
go 1.20
|
||||
go 1.19
|
||||
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d h1:Vcb7YkZuUSSIC+WF/xV3UDfHbAxZgyT2zGleJP3Ig5k=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d/go.mod h1:/vrbWSHc7YS1KSYhVOyyeucXW/e+1DkVBOgnBEXUCeY=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
module github.com/nspcc-dev/neo-go/examples/iterator
|
||||
|
||||
go 1.20
|
||||
go 1.19
|
||||
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d h1:Vcb7YkZuUSSIC+WF/xV3UDfHbAxZgyT2zGleJP3Ig5k=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d/go.mod h1:/vrbWSHc7YS1KSYhVOyyeucXW/e+1DkVBOgnBEXUCeY=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
|
||||
|
|
|
@ -27,4 +27,4 @@
|
|||
"extra": {
|
||||
"Tokens": null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
module github.com/nspcc-dev/neo-go/examples/nft
|
||||
|
||||
go 1.20
|
||||
go 1.19
|
||||
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d h1:Vcb7YkZuUSSIC+WF/xV3UDfHbAxZgyT2zGleJP3Ig5k=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d/go.mod h1:/vrbWSHc7YS1KSYhVOyyeucXW/e+1DkVBOgnBEXUCeY=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
module github.com/nspcc-dev/neo-go/examples/nft-nd-nns
|
||||
|
||||
go 1.20
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/nspcc-dev/neo-go v0.102.1-0.20231020181554-d89c8801d689
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2
|
||||
github.com/stretchr/testify v1.8.4
|
||||
)
|
||||
|
||||
|
@ -45,15 +45,15 @@ require (
|
|||
go.uber.org/atomic v1.10.0 // indirect
|
||||
go.uber.org/multierr v1.9.0 // indirect
|
||||
go.uber.org/zap v1.24.0 // indirect
|
||||
golang.org/x/crypto v0.17.0 // indirect
|
||||
golang.org/x/crypto v0.14.0 // indirect
|
||||
golang.org/x/mod v0.12.0 // indirect
|
||||
golang.org/x/sync v0.3.0 // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
golang.org/x/term v0.15.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
golang.org/x/term v0.13.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
rsc.io/tmplfunc v0.0.3 // indirect
|
||||
)
|
||||
|
|
|
@ -200,8 +200,8 @@ github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22/go.mod h
|
|||
github.com/nspcc-dev/hrw v1.0.9 h1:17VcAuTtrstmFppBjfRiia4K2wA/ukXZhLFS8Y8rz5Y=
|
||||
github.com/nspcc-dev/neo-go v0.102.1-0.20231020181554-d89c8801d689 h1:WnEdGAQwaW0C8wnNnQZ+rM/JfFKZDSTOqwm8cS0TOdk=
|
||||
github.com/nspcc-dev/neo-go v0.102.1-0.20231020181554-d89c8801d689/go.mod h1:x+wmcYqpZYJwLp1l/pHZrqNp3RSWlkMymWGDij3/OPo=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d h1:Vcb7YkZuUSSIC+WF/xV3UDfHbAxZgyT2zGleJP3Ig5k=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d/go.mod h1:/vrbWSHc7YS1KSYhVOyyeucXW/e+1DkVBOgnBEXUCeY=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
|
||||
github.com/nspcc-dev/neofs-api-go/v2 v2.14.0 h1:jhuN8Ldqz7WApvUJRFY0bjRXE1R3iCkboMX5QVZhHVk=
|
||||
github.com/nspcc-dev/neofs-crypto v0.4.0 h1:5LlrUAM5O0k1+sH/sktBtrgfWtq1pgpDs09fZo+KYi4=
|
||||
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11 h1:QOc8ZRN5DXlAeRPh5QG9u8rMLgoeRNiZF5/vL7QupWg=
|
||||
|
@ -298,8 +298,8 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
|
|||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
|
@ -431,12 +431,12 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
@ -444,8 +444,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
|||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
@ -574,8 +574,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
|
|||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
module github.com/nspcc-dev/neo-go/examples/nft-nd
|
||||
|
||||
go 1.20
|
||||
go 1.19
|
||||
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d h1:Vcb7YkZuUSSIC+WF/xV3UDfHbAxZgyT2zGleJP3Ig5k=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d/go.mod h1:/vrbWSHc7YS1KSYhVOyyeucXW/e+1DkVBOgnBEXUCeY=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
module github.com/nspcc-dev/neo-go/examples/oracle
|
||||
|
||||
go 1.20
|
||||
go 1.19
|
||||
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d h1:Vcb7YkZuUSSIC+WF/xV3UDfHbAxZgyT2zGleJP3Ig5k=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d/go.mod h1:/vrbWSHc7YS1KSYhVOyyeucXW/e+1DkVBOgnBEXUCeY=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
module github.com/nspcc-dev/neo-go/examples/runtime
|
||||
|
||||
go 1.20
|
||||
go 1.19
|
||||
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d h1:Vcb7YkZuUSSIC+WF/xV3UDfHbAxZgyT2zGleJP3Ig5k=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d/go.mod h1:/vrbWSHc7YS1KSYhVOyyeucXW/e+1DkVBOgnBEXUCeY=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
module github.com/nspcc-dev/neo-go/examples/storage
|
||||
|
||||
go 1.20
|
||||
go 1.19
|
||||
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d h1:Vcb7YkZuUSSIC+WF/xV3UDfHbAxZgyT2zGleJP3Ig5k=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d/go.mod h1:/vrbWSHc7YS1KSYhVOyyeucXW/e+1DkVBOgnBEXUCeY=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
module github.com/nspcc-dev/neo-go/examples/timer
|
||||
|
||||
go 1.20
|
||||
go 1.19
|
||||
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d h1:Vcb7YkZuUSSIC+WF/xV3UDfHbAxZgyT2zGleJP3Ig5k=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d/go.mod h1:/vrbWSHc7YS1KSYhVOyyeucXW/e+1DkVBOgnBEXUCeY=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
module github.com/nspcc-dev/neo-go/examples/token
|
||||
|
||||
go 1.20
|
||||
go 1.19
|
||||
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d h1:Vcb7YkZuUSSIC+WF/xV3UDfHbAxZgyT2zGleJP3Ig5k=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d/go.mod h1:/vrbWSHc7YS1KSYhVOyyeucXW/e+1DkVBOgnBEXUCeY=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
|
||||
|
|
|
@ -31,25 +31,20 @@ to organize the ceremony and generate proving and verifying keys for a circuit.
|
|||
However, both phases take a significant amount of time and computations to be
|
||||
performed. Luckily for the developers, it is possible to omit a curve-specific
|
||||
part of the MPC and reuse the existing results of Phase 1 got from a trusted
|
||||
source, e.g. from [Zcash PowersOfTau](https://github.com/ZcashFoundation/powersoftau-attestations)
|
||||
held by the [Zcash Foundation](https://github.com/ZcashFoundation).
|
||||
source, e.g. from [Powers of Tau ceremony](https://github.com/filecoin-project/powersoftau/)
|
||||
held by the [Filecoin project](https://github.com/filecoin-project/phase2-attestations#phase1).
|
||||
`TestCubicCircuit_EndToEnd_Prod` test of the current circuit example demonstrates
|
||||
how to use the `response` output file from the Phase 1 of the Filecoin's Powers
|
||||
of Tau ceremony for BLS12-381 curve:
|
||||
* [`response8`](./response8) file is the response output from the ceremony that was run locally
|
||||
based on the [Filecoin Powers of Tau](https://github.com/filecoin-project/powersoftau/)
|
||||
with the `REQUIRED_POWER` set to 8 (to reduce computations and response file size).
|
||||
The ceremony itself was run with the help of [testing script](https://github.com/filecoin-project/powersoftau/blob/master/test.sh).
|
||||
* [`response8`](./response8) file is the response output from the [Powers of Tau ceremony](https://github.com/filecoin-project/powersoftau/)
|
||||
with the `REQUIRED_POWER` set to 8 (to reduce computations and response file size)
|
||||
that was run locally with the help of [testing script](https://github.com/filecoin-project/powersoftau/blob/master/test.sh).
|
||||
To get the response file for a production environment, the user has two options:
|
||||
1. Organize his own ceremony with required number of powers following the
|
||||
[guide](https://github.com/filecoin-project/powersoftau/tree/master#instructions)
|
||||
from the ceremony source repo.
|
||||
2. Download the existing suitable `response` file from the trusted existing ceremony.
|
||||
Please, be careful while choosing `response` file and ensure that it has enough
|
||||
powers computed (at least as much as the number of the circuit's constraints requires).
|
||||
Example of suitable ceremonies:
|
||||
* Zcash Powers Of Tau [attestations page](https://github.com/ZcashFoundation/powersoftau-attestations) (up to 2^21)
|
||||
* Filecoin Perpetual Powers Of Tau [attestations page](https://github.com/arielgabizon/perpetualpowersoftau#perpetual-powers-of-tau-for-bls381) (up to 2^27)
|
||||
from the source repo.
|
||||
2. Download the existing suitable `response` file from the
|
||||
[attestations page](https://github.com/arielgabizon/perpetualpowersoftau#perpetual-powers-of-tau-for-bls381).
|
||||
* [main_test](./main_test.go) contains the `TestCubicCircuit_EndToEnd_Prod` test
|
||||
itself and demonstrates how to properly initialize Phase 2 based on the given
|
||||
response file and make some dummy contributions into it.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module github.com/nspcc-dev/neo-go/examples/zkp/cubic
|
||||
|
||||
go 1.20
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/consensys/gnark v0.9.1
|
||||
|
@ -33,7 +33,6 @@ require (
|
|||
github.com/mmcloughlin/addchain v0.4.0 // indirect
|
||||
github.com/mr-tron/base58 v1.2.0 // indirect
|
||||
github.com/nspcc-dev/go-ordered-json v0.0.0-20231123160306-3374ff1e7a3c // indirect
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d // indirect
|
||||
github.com/nspcc-dev/rfc6979 v0.2.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_golang v1.13.0 // indirect
|
||||
|
@ -51,15 +50,15 @@ require (
|
|||
go.uber.org/atomic v1.10.0 // indirect
|
||||
go.uber.org/multierr v1.9.0 // indirect
|
||||
go.uber.org/zap v1.24.0 // indirect
|
||||
golang.org/x/crypto v0.17.0 // indirect
|
||||
golang.org/x/crypto v0.14.0 // indirect
|
||||
golang.org/x/mod v0.12.0 // indirect
|
||||
golang.org/x/sync v0.3.0 // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
golang.org/x/term v0.15.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
golang.org/x/term v0.13.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
rsc.io/tmplfunc v0.0.3 // indirect
|
||||
)
|
||||
|
|
|
@ -216,8 +216,7 @@ github.com/nspcc-dev/go-ordered-json v0.0.0-20231123160306-3374ff1e7a3c/go.mod h
|
|||
github.com/nspcc-dev/hrw v1.0.9 h1:17VcAuTtrstmFppBjfRiia4K2wA/ukXZhLFS8Y8rz5Y=
|
||||
github.com/nspcc-dev/neo-go v0.103.1 h1:BfRBceHUu8jSc1KQy7CzmQ/pa+xzAmgcyteGf0/IGgM=
|
||||
github.com/nspcc-dev/neo-go v0.103.1/go.mod h1:MD7MPiyshUwrE5n1/LzxeandbItaa/iLW/bJb6gNs/U=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d h1:Vcb7YkZuUSSIC+WF/xV3UDfHbAxZgyT2zGleJP3Ig5k=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d/go.mod h1:/vrbWSHc7YS1KSYhVOyyeucXW/e+1DkVBOgnBEXUCeY=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231020160724-c3955f87d1b5 h1:09CpI5uwsxb1EeFPIKQRwwWlfCmDD/Dwwh01lPiQScM=
|
||||
github.com/nspcc-dev/neofs-api-go/v2 v2.14.0 h1:jhuN8Ldqz7WApvUJRFY0bjRXE1R3iCkboMX5QVZhHVk=
|
||||
github.com/nspcc-dev/neofs-crypto v0.4.0 h1:5LlrUAM5O0k1+sH/sktBtrgfWtq1pgpDs09fZo+KYi4=
|
||||
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11 h1:QOc8ZRN5DXlAeRPh5QG9u8rMLgoeRNiZF5/vL7QupWg=
|
||||
|
@ -318,8 +317,8 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
|
|||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
|
@ -455,12 +454,12 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
@ -468,8 +467,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
|||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
@ -598,8 +597,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
|
|||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package cubic
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
@ -157,12 +156,6 @@ func TestCubicCircuit_EndToEnd(t *testing.T) {
|
|||
// result for proving/verifying keys generation and demonstrates how to contribute
|
||||
// some randomness into it.
|
||||
func TestCubicCircuit_EndToEnd_Prod(t *testing.T) {
|
||||
const (
|
||||
// Response file generated locally for 2^8 powers.
|
||||
pathToResponseFile = "./response8"
|
||||
// The order of Powers of Tau ceremony, it depends on the response file.
|
||||
orderOfResponseFile = 8
|
||||
)
|
||||
var (
|
||||
circuit CubicCircuit
|
||||
assignment = CubicCircuit{X: 3, Y: 35}
|
||||
|
@ -173,10 +166,8 @@ func TestCubicCircuit_EndToEnd_Prod(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
// Setup (groth16 zkSNARK), use MPC-based solution for proving and verifying
|
||||
// keys generation. Please, be careful while adopting this code for your circuit.
|
||||
// Ensure that response file that you've provided contains enough powers computed
|
||||
// so that the number of constraints in your circuit can be handled.
|
||||
pk, vk := setup(t, ccs, pathToResponseFile, orderOfResponseFile)
|
||||
// keys generation.
|
||||
pk, vk := setup(t, ccs, "./response8", 8) // the order of Powers of Tau ceremony, depends on the response file.
|
||||
|
||||
// Intermediate step: witness definition.
|
||||
witness, err := frontend.NewWitness(&assignment, ecc.BLS12_381.ScalarField())
|
||||
|
@ -271,21 +262,20 @@ func setup(t *testing.T, ccs constraint.ConstraintSystem, phase1ResponsePath str
|
|||
beta_coef_g1 := make([]curve.G1Affine, inN)
|
||||
|
||||
// Accumulator serialization: https://github.com/filecoin-project/powersoftau/blob/ab8f85c28f04af5a99cfcc93a3b1f74c06f94105/src/accumulator.rs#L111
|
||||
errMessage := fmt.Sprintf("ensure your response file contains exactly 2^%d powers of tau for BLS12-381 curve", inPow)
|
||||
for i := range coef_g1 {
|
||||
require.NoError(t, dec.Decode(&coef_g1[i]), errMessage)
|
||||
require.NoError(t, dec.Decode(&coef_g1[i]))
|
||||
}
|
||||
for i := range coef_g2 {
|
||||
require.NoError(t, dec.Decode(&coef_g2[i]), errMessage)
|
||||
require.NoError(t, dec.Decode(&coef_g2[i]))
|
||||
}
|
||||
for i := range alpha_coef_g1 {
|
||||
require.NoError(t, dec.Decode(&alpha_coef_g1[i]), errMessage)
|
||||
require.NoError(t, dec.Decode(&alpha_coef_g1[i]))
|
||||
}
|
||||
for i := range beta_coef_g1 {
|
||||
require.NoError(t, dec.Decode(&beta_coef_g1[i]), errMessage)
|
||||
require.NoError(t, dec.Decode(&beta_coef_g1[i]))
|
||||
}
|
||||
beta_g2 := &curve.G2Affine{}
|
||||
require.NoError(t, dec.Decode(beta_g2), errMessage)
|
||||
require.NoError(t, dec.Decode(beta_g2))
|
||||
|
||||
// Transform (take exactly those number of powers that needed for the given number of constraints).
|
||||
var (
|
||||
|
@ -296,9 +286,6 @@ func setup(t *testing.T, ccs constraint.ConstraintSystem, phase1ResponsePath str
|
|||
}
|
||||
outN := int64(math.Pow(2, float64(outPow)))
|
||||
|
||||
if len(coef_g1) < int(2*outN-1) {
|
||||
t.Fatalf("number of circuit constraints is too large for the provided response file: nbConstraints is %d, required at least %d powers to be computed", numConstraints, outN)
|
||||
}
|
||||
srs1 := mpcsetup.Phase1{}
|
||||
srs1.Parameters.G1.Tau = coef_g1[:2*outN-1] // outN + (outN-1)
|
||||
srs1.Parameters.G2.Tau = coef_g2[:outN] // outN
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
module github.com/nspcc-dev/neo-go/examples/zkp/xor
|
||||
|
||||
go 1.20
|
||||
go 1.19
|
||||
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue