From ddc4383afa8e5eb7e5fb64613e0d870ee0087455 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 4 Oct 2023 17:43:55 +0300 Subject: [PATCH] *: migrate onto gnark@v0.9.0 and add production CRS generation instructions 1. Close #3079 by using new exported gnark@v0.9.0 APIs. 2. Add an example and instructions for production CRS generation. Signed-off-by: Anna Shaleva --- examples/zkp/cubic_circuit/README.md | 56 +++++++ examples/zkp/cubic_circuit/go.mod | 23 ++- examples/zkp/cubic_circuit/go.sum | 86 ++++------- examples/zkp/cubic_circuit/main_test.go | 187 +++++++++++++++++++++++- examples/zkp/cubic_circuit/response8 | Bin 0 -> 74992 bytes go.mod | 21 +-- go.sum | 57 ++++---- pkg/smartcontract/zkpbinding/binding.go | 90 +++--------- 8 files changed, 347 insertions(+), 173 deletions(-) create mode 100644 examples/zkp/cubic_circuit/README.md create mode 100644 examples/zkp/cubic_circuit/response8 diff --git a/examples/zkp/cubic_circuit/README.md b/examples/zkp/cubic_circuit/README.md new file mode 100644 index 0000000000..81691acfe7 --- /dev/null +++ b/examples/zkp/cubic_circuit/README.md @@ -0,0 +1,56 @@ + ### Example description + + This example demonstrates how to create your own circuit and generate Groth-16 + proof based on BLS12-381 elliptic curve points with the help of + [consensys/gnark](https://pkg.go.dev/github.com/consensys/gnark). It also shows how to generate, deploy and invoke Verifier + smart contract to verify proofs for the given circuit on the Neo chain with the + help of [zkpbindings](https://pkg.go.dev/github.com/nspcc-dev/neo-go/pkg/smartcontract/zkpbinding) NeoGo package. The package also contains circuit + tests implemented with [gnark/test](https://pkg.go.dev/github.com/consensys/gnark/test) to check the circuit validity and + end-to-end proof generation/verification test implemented with [neotest](https://pkg.go.dev/github.com/nspcc-dev/neo-go/pkg/neotest) + to demonstrate how to build, deploy and verify proofs via Verifier smart + contract for the given circuit. + +### Groth-16 setup notes + +Common reference string (CRS) is needed to generate proving and verifying keys +for the given constrained system. In production environment, CRS generation can +be performed via Multi-Party Computation (MPC) ceremony that includes two +phases: Phase 1 (a.k.a. Powers of Tau) that is curve-specific and those +results may be used by all circuits; and Phase 2 that is circuit-specific and +uses the result of Phase 1 as an input. + +For testing setups, check out the [`TestCubicCircuit_EndToEnd`](./main_test.go) +keys generation stage. For production usage, read the information below. + +Both phases for BLS12-381 curve can be implemented in the Go programming language +using the corresponding `consensys/gnark` API (see the +[test example](https://github.com/Consensys/gnark/blob/36b0b58f02d0381774b24efba0a48032e5f794b4/backend/groth16/bls12-381/mpcsetup/setup_test.go#L34)) +and the example of a +[CLI tool that uses the API with BN254 elliptic curve](https://github.com/bnb-chain/zkbnb-setup) +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 [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 [Powers of Tau ceremony] + 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 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. + +Take the [`TestCubicCircuit_EndToEnd_Prod`](./main_test.go) test logic as a basis +while generating the circuit-specific proving and verifying keys for the production +usage. Currently, we don't have a BLS12-381 specific Groth-16 setup CLI utility +like for [https://github.com/bnb-chain/zkbnb-setup](BN254), but eventually it will +be included into the NeoGo toolkit to make the development process easier. \ No newline at end of file diff --git a/examples/zkp/cubic_circuit/go.mod b/examples/zkp/cubic_circuit/go.mod index 8ce973d745..9ab004aa42 100644 --- a/examples/zkp/cubic_circuit/go.mod +++ b/examples/zkp/cubic_circuit/go.mod @@ -3,8 +3,8 @@ module cubic go 1.18 require ( - github.com/consensys/gnark v0.8.1 - github.com/consensys/gnark-crypto v0.9.2 + github.com/consensys/gnark v0.9.0 + github.com/consensys/gnark-crypto v0.11.2 github.com/nspcc-dev/neo-go v0.102.0 github.com/stretchr/testify v1.8.4 ) @@ -12,24 +12,23 @@ require ( require ( github.com/benbjohnson/clock v1.1.0 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bits-and-blooms/bitset v1.7.0 // indirect + github.com/bits-and-blooms/bitset v1.8.0 // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect - github.com/fxamacker/cbor/v2 v2.4.0 // indirect + github.com/fxamacker/cbor/v2 v2.5.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.1 // indirect - github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect + github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b // indirect github.com/google/uuid v1.3.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/hashicorp/golang-lru v0.6.0 // indirect github.com/holiman/uint256 v1.2.0 // indirect - github.com/kr/text v0.2.0 // indirect - github.com/mattn/go-colorable v0.1.12 // indirect - github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/mr-tron/base58 v1.2.0 // indirect @@ -40,8 +39,7 @@ require ( github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.37.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect - github.com/rogpeppe/go-internal v1.11.0 // indirect - github.com/rs/zerolog v1.29.0 // indirect + github.com/rs/zerolog v1.30.0 // indirect github.com/russross/blackfriday/v2 v2.0.1 // indirect github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 // indirect @@ -58,10 +56,11 @@ require ( golang.org/x/sys v0.11.0 // indirect golang.org/x/term v0.11.0 // indirect golang.org/x/text v0.12.0 // indirect - golang.org/x/tools v0.11.1 // 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.31.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) -replace github.com/nspcc-dev/neo-go => ../../../ \ No newline at end of file +replace github.com/nspcc-dev/neo-go => ../../../ diff --git a/examples/zkp/cubic_circuit/go.sum b/examples/zkp/cubic_circuit/go.sum index e194290fcc..56287a0d4c 100644 --- a/examples/zkp/cubic_circuit/go.sum +++ b/examples/zkp/cubic_circuit/go.sum @@ -45,36 +45,30 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bits-and-blooms/bitset v1.7.0 h1:YjAGVd3XmtK9ktAbX8Zg2g2PwLIMjGREZJHlV4j7NEo= -github.com/bits-and-blooms/bitset v1.7.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= +github.com/bits-and-blooms/bitset v1.8.0 h1:FD+XqgOZDUxxZ8hzoBFuV9+cGWY9CslN6d5MS5JVb4c= +github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/readline v1.5.0 h1:lSwwFrbNviGePhkewF1az4oLmcwqCZijQ2/Wi3BGHAI= +github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= -github.com/consensys/gnark v0.8.0 h1:0bQ2MyDG4oNjMQpNyL8HjrrUSSL3yYJg0Elzo6LzmcU= -github.com/consensys/gnark v0.8.0/go.mod h1:aKmA7dIiLbTm0OV37xTq0z+Bpe4xER8EhRLi6necrm8= -github.com/consensys/gnark v0.8.1 h1:zXM6iFejCJSwqkZsjS/qMQGLEyX0rg8nRhwuEwzj3bg= -github.com/consensys/gnark v0.8.1/go.mod h1:PsGdLgX5nBy9EsDbqBkvTncZbfT69MizMsveGAsHBbo= -github.com/consensys/gnark-crypto v0.9.2 h1:a4gsSAnQNgrt8dqxsd49H2rtLQPoekZCWpCmcKPRNus= -github.com/consensys/gnark-crypto v0.9.2/go.mod h1:a2DQL4+5ywF6safEeZFEPGRiiGbjzGFRUN2sg06VuU4= +github.com/consensys/gnark v0.9.0 h1:OoOr0Q771mQINVdP3s1AF2Rs1y8gtXhWVkadz/9KmZc= +github.com/consensys/gnark v0.9.0/go.mod h1:Sy9jJjIaGJFfNeupyNOR9Ei2IbAB6cfCO78DfG27YvM= github.com/consensys/gnark-crypto v0.11.2 h1:GJjjtWJ+db1xGao7vTsOgAOGgjfPe7eRGPL+xxMX0qE= github.com/consensys/gnark-crypto v0.11.2/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= -github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -88,8 +82,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88= -github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= +github.com/fxamacker/cbor/v2 v2.5.0 h1:oHsG0V/Q6E/wqTS2O1Cozzsy69nqCiguo5Q1a1ADivE= +github.com/fxamacker/cbor/v2 v2.5.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -130,7 +124,6 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= @@ -158,8 +151,8 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= +github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b h1:h9U78+dx9a4BKdQkBBos92HalKpaGKHrp+3Uo6yTodo= +github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= @@ -195,12 +188,14 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= -github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= @@ -219,14 +214,10 @@ github.com/nspcc-dev/dbft v0.0.0-20230515113611-25db6ba61d5c h1:uyK5aLbAhrnZtnvo github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 h1:n4ZaFCKt1pQJd7PXoMJabZWK9ejjbLOVrkl/lOUmshg= github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22/go.mod h1:79bEUDEviBHJMFV6Iq6in57FEOCMcRhfQnfaf0ETA5U= github.com/nspcc-dev/hrw v1.0.9 h1:17VcAuTtrstmFppBjfRiia4K2wA/ukXZhLFS8Y8rz5Y= -github.com/nspcc-dev/neo-go v0.101.2-0.20230614180905-3e1875218271 h1:0dtQNWEl/sADN1lh65NHL/0P4NMwC2rYpUQG087P/JM= -github.com/nspcc-dev/neo-go v0.101.2-0.20230614180905-3e1875218271/go.mod h1:PHOHpvm02STB7G+9Crp7HQdgwc8vRz65TaO4rwqUd9E= -github.com/nspcc-dev/neo-go v0.102.0/go.mod h1:QXxpZxJT2KedwM0Nlj8UO0/fZN2WIe4h/i03uBHKbnc= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a h1:63sh46kfKF/g2IE1z/EV8CBEKCVmGJXSSH0ZHqTDGCY= github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230810094130-11bb733f1a2c h1:upj+XyoI0dS7CYnZOTAeyuznhvDIJurQXL4FvHNKyl4= 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.9 h1:uIQlWUUo5n/e8rLFGm14zIValcpXU1HWuwaoXUAHt5Q= +github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11 h1:QOc8ZRN5DXlAeRPh5QG9u8rMLgoeRNiZF5/vL7QupWg= github.com/nspcc-dev/rfc6979 v0.2.0 h1:3e1WNxrN60/6N0DW7+UYisLeZJyfqZTNOjeV/toYvOE= github.com/nspcc-dev/rfc6979 v0.2.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso= github.com/nspcc-dev/tzhash v1.7.0 h1:/+aL33NC7y5OIGnY2kYgjZt8mg7LVGFMdj/KAJLndnk= @@ -273,10 +264,9 @@ github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5 github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.29.0 h1:Zes4hju04hjbvkVkOhdl2HpZa+0PmVwigmo8XoORE5w= -github.com/rs/zerolog v1.29.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c= +github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= @@ -287,15 +277,9 @@ github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrf github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 h1:xQdMZ1WLrgkkvOZ/LDQxjVxMLdby7osSh4ZEVa5sIjs= @@ -331,8 +315,6 @@ 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.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= -golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -345,7 +327,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb h1:PaBZQdo+iSDyHT053FjUCgZQ/9uqVwPOcl7KSWhKn6w= +golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -366,8 +348,6 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -404,7 +384,7 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -422,8 +402,6 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -472,14 +450,12 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/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.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= -golang.org/x/sys v0.8.0/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.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= golang.org/x/sys v0.11.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.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -489,8 +465,6 @@ 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.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -536,10 +510,8 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE= -golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= -golang.org/x/tools v0.11.1 h1:ojD5zOW8+7dOGzdnNgersm8aPfcDjhMp12UfG93NIMc= -golang.org/x/tools v0.11.1/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8= +golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E= +golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -595,8 +567,9 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 h1:PDIOdWxZ8eRizhKa1AAvY53xsvLB1cWorMjslvY3VA8= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -609,7 +582,7 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.48.0 h1:rQOsyJ/8+ufEDJd/Gdsz7HG220Mh9HAhFHRGnIjda0w= +google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -622,8 +595,6 @@ 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.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 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= @@ -642,7 +613,6 @@ gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/examples/zkp/cubic_circuit/main_test.go b/examples/zkp/cubic_circuit/main_test.go index b03790355a..358e929ab0 100644 --- a/examples/zkp/cubic_circuit/main_test.go +++ b/examples/zkp/cubic_circuit/main_test.go @@ -1,12 +1,18 @@ package cubic import ( + "bytes" + "math" "os" "path/filepath" "testing" "github.com/consensys/gnark-crypto/ecc" + curve "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark/backend/groth16" + "github.com/consensys/gnark/backend/groth16/bls12-381/mpcsetup" + "github.com/consensys/gnark/constraint" + cs "github.com/consensys/gnark/constraint/bls12-381" "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/frontend/cs/r1cs" "github.com/consensys/gnark/test" @@ -74,7 +80,10 @@ func TestCubicCircuit_EndToEnd(t *testing.T) { ccs, err := frontend.Compile(ecc.BLS12_381.ScalarField(), r1cs.NewBuilder, &circuit) require.NoError(t, err) - // One time setup (groth16 zkSNARK). + // One time setup (groth16 zkSNARK). Built-in groth16.Setup function is used + // for the test purposes. In production environment it is recommended to use + // MPC-based solution for proving and verifying keys generation, see the + // TestCubicCircuit_EndToEnd_Prod test. pk, vk, err := groth16.Setup(ccs) require.NoError(t, err) @@ -140,3 +149,179 @@ func TestCubicCircuit_EndToEnd(t *testing.T) { validatorInvoker := e.ValidatorInvoker(c.Hash) validatorInvoker.Invoke(t, true, "verifyProof", args.A, args.B, args.C, args.PublicWitnesses) } + +// TestCubicCircuit_EndToEnd shows how to generate proof for pre-defined cubic circuit, +// how to generate Go verification contract that can be compiled by NeoGo and deployed +// to the chain and how to verify proofs via verification contract invocation. It +// differs from TestCubicCircuit_EndToEnd in that it uses pre-generated Powers of Tau +// result for proving/verifying keys generation and demonstrates how to contribute +// some randomness into it. +func TestCubicCircuit_EndToEnd_Prod(t *testing.T) { + var ( + circuit CubicCircuit + assignment = CubicCircuit{X: 3, Y: 35} + ) + + // Compile our circuit into a R1CS (a constraint system). + ccs, err := frontend.Compile(ecc.BLS12_381.ScalarField(), r1cs.NewBuilder, &circuit) + require.NoError(t, err) + + // Setup (groth16 zkSNARK), use MPC-based solution for proving and verifying + // 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()) + require.NoError(t, err) + publicWitness, err := witness.Public() + require.NoError(t, err) + + // Proof creation (groth16). + proof, err := groth16.Prove(ccs, pk, witness) + require.NoError(t, err) + + // Ensure that gnark can successfully verify the proof (just in case). + err = groth16.Verify(proof, vk, publicWitness) + require.NoError(t, err) + + // Now, when we're sure that the proof is valid, we can create and deploy verification + // contract to the Neo testing chain. + args, err := zkpbinding.GetVerifyProofArgs(proof, publicWitness) + require.NoError(t, err) + + // Create contract file. + tmpDir := t.TempDir() + srcPath := filepath.Join(tmpDir, "verify.go") + f, err := os.Create(srcPath) + require.NoError(t, err) + + // Create contract configuration file. + cfgPath := filepath.Join(tmpDir, "verify.yml") + fCfg, err := os.Create(cfgPath) + require.NoError(t, err) + + // Create contract go.mod and go.sum files. + fMod, err := os.Create(filepath.Join(tmpDir, "go.mod")) + require.NoError(t, err) + fSum, err := os.Create(filepath.Join(tmpDir, "go.sum")) + require.NoError(t, err) + + err = zkpbinding.GenerateVerifier(zkpbinding.Config{ + VerifyingKey: vk, + Output: f, + CfgOutput: fCfg, + GomodOutput: fMod, + GosumOutput: fSum, + }) + require.NoError(t, err) + + require.NoError(t, f.Close()) + require.NoError(t, fCfg.Close()) + require.NoError(t, fMod.Close()) + require.NoError(t, fSum.Close()) + + // Create testing chain and deploy contract onto it. + bc, committee := chain.NewSingle(t) + e := neotest.NewExecutor(t, bc, committee, committee) + + // Compile verification contract and deploy the contract onto chain. + c := neotest.CompileFile(t, e.Validator.ScriptHash(), srcPath, cfgPath) + e.DeployContract(t, c, nil) + + // Verify proof via verification contract call. + validatorInvoker := e.ValidatorInvoker(c.Hash) + validatorInvoker.Invoke(t, true, "verifyProof", args.A, args.B, args.C, args.PublicWitnesses) +} + +// setup generates proving and verifying keys for the given compiled constrained +// system. It accepts path to the response file from Phase 1 of the Powers of Tau +// ceremony for the BLS12-381 curve and the power of the ceremony. +// See the README.md for details on the Phase 1 response file. It makes +// circuit-specific Phase 2 initialisation of the MPC ceremony and performs some +// dummy contributions for Phase 2. In production environment, participant will +// receive a []byte, deserialize it, add his contribution and send back to the +// coordinator. +func setup(t *testing.T, ccs constraint.ConstraintSystem, phase1ResponsePath string, inPow int) (groth16.ProvingKey, groth16.VerifyingKey) { + const ( + nContributionsPhase2 = 3 + blake2bHashSize = 64 + ) + + f, err := os.Open(phase1ResponsePath) + require.NoError(t, err) + + // Skip hash of the previous contribution, don't need it for the MPC initialisation. + _, err = f.Seek(blake2bHashSize, 0) + require.NoError(t, err) + dec := curve.NewDecoder(f) + + // Retrieve parameters. + inN := int(math.Pow(2, float64(inPow))) + coef_g1 := make([]curve.G1Affine, 2*inN-1) + coef_g2 := make([]curve.G2Affine, inN) + alpha_coef_g1 := make([]curve.G1Affine, inN) + beta_coef_g1 := make([]curve.G1Affine, inN) + + // Accumulator serialization: https://github.com/filecoin-project/powersoftau/blob/ab8f85c28f04af5a99cfcc93a3b1f74c06f94105/src/accumulator.rs#L111 + for i := range coef_g1 { + require.NoError(t, dec.Decode(&coef_g1[i])) + } + for i := range coef_g2 { + require.NoError(t, dec.Decode(&coef_g2[i])) + } + for i := range alpha_coef_g1 { + require.NoError(t, dec.Decode(&alpha_coef_g1[i])) + } + for i := range beta_coef_g1 { + require.NoError(t, dec.Decode(&beta_coef_g1[i])) + } + beta_g2 := &curve.G2Affine{} + require.NoError(t, dec.Decode(beta_g2)) + + // Transform (take exactly those number of powers that needed for the given number of constraints). + var ( + numConstraints = ccs.GetNbConstraints() + outPow int + ) + for ; 1<wYdK&NhI`9hHBF4M1U9ulP0FXbRkq=nQ4qr{?6ruXDJeRLiIv0keEK2g7uFPF2 zbExv$TkNT`8?o=B@x~-n%jqZSzqO=c-`(2OLNyb=gV|e&&N)^NH@KI~75%_%=oxQ6ZEM#`$vMj}(qSThTR}q2 zGFcIbm&Km1KF^F65TDUT0L;IrqT=2KcF{bfW-?RFNvyY~2Ufc`>Y-~ULZlPX{aT=w zi`Q6HF~u4^{5n!NqQhS!OGpqg^X!S5%MlWk8yFC8RY0pj3ypM?@X1?tbeWZxo`NE< zq5+EYiA4#>um%G(V}*L?>IM8c7c#|2!QvwPziSE)IMPait_1#8+j1JEcGB%uRpL8d z1`&mh`CYL?wp?C{6aTDgvYv=p3^|@;W$$HcUDFZp`maS8`P)X6b>Pif5efRF;_X;p zN+jx7RK9A^qA;3yOlr_8X`h{BlB+2<9YR%cr2$()vh=9P0GD^hyc+1_x1W zUfbdG$SRsuxQM)1I+~pnN`D~Fks%WCf$yP1OVI&4&R5#?KH7$-yaH}>iH;C`BX0%4u&DE(HvwEKN)jcHK z{?9O1dmGT@nZ{Ae5>23V%a3=GqNWsF7E&RDQ7v9gDAkdr8EkR{8b^I`b>HM18UFF? z`p1EP?NuTiaP1^CPLYt9!=y+9$=+sN)#v#o$slBt9J$W)(_5Beu9$o75f5h1vmJVQ z^6J6}q?D-@)yRyE{~%f9#_mcl7yM1IoFTOfChSo6g{9fm5EMF2o>fG6*?v@B7@cs- z$MI--g*AGXh4OVx|B6YGp?S#>Ky(&adK8l}cjd~TvFBP%4 zDu2ziWe_}u$8lwEW#d~r9}{*!iQ8N{WD&ff)eii@X~o#V z7;K44FlU|2%GF?O9B`?>XNQ(_Zp@5~{5=Ldq7et{@*hW#|8;4xRJ@?AIj9e$!4QsP z;Pk;VEG?J$g;I6Hq^;m`*=Jih0sZPPhKqNrBtODYnZR_-fd-s-vsQp_XV}gpXmA;Fw|tmpfarMOB;QPeu!Ql` z13-z!gK^?EtBra-1O-l6;6eP1UJoEgwO`_#fL310u_<_;f}n?8f#LLJVNKM;F3L6e zeR@4^xT8fQ4sn_G+yx4f&p_DaqB~7yOVv0IFIL~meE+JFgM#L}M{;D3s3ZZ1T%5BE zbrae%e(aOW_9TqB1Cfrcu`VrZd-`Pw*7V35=#PQTflhUfLU}tJM)x|-z*8sJ z83=8}r^wx)8VQ?IldJV;z5Cx<7x1fgs@3#9W7@bCusDgN8?3hz02(qpog3m1R5d%a zL4$Sd8sWqGkHmpH(wizk^W=B-YBZS?c8lW>PoxLA7M_{WxX#IciByrwL4?m2BP7#xi}R{3-fuAq23@QNvX#$SW}b zz_Dq1A@iLty3bZ3DI%Oi!vaYjQU-*V?OPKuh@SUZmjA(tgY4`VwM}G}eq^h7J}=bo z?bO$$m=p4SCxs_R!h$*F+ohI<36s2s+p%mz(}*5m!CyR_nG%lzn2T+e7uRC`kYHew&i}Pt_pM=IL=e{bb zS>@RHOKNihM2cyctILcU%tK~{uCrXOKtiCdmTA|vxUHg+^kw(>gw(*U-)>%!pbX)7 z?-1Yo>Xj0Uohyd6wgqqN~fBuBjrrJZX<%jldp9QTdT`NX;!Y#gEbrox0jmg%f ziwECkxV3Q2jzoB2l3ucEE$9DVenm{o;L)7ZrEdGFsJxG}KU1cIGx>J;aZX626&cA; z5%Rg(fOwJ>b2eZznIve6i6*xz_Vz-X6-Er6!g@XGO(yi$CU_f0`hbasCBNvi?jTt@ z7)1{MvOj{E4v+sL<%kWwle0X!>+VuHzVfomOu< zQ7ZhN^C49vm*K8QT6|(@lop5)1T~j}2r>&V0d6GK$1(?{1iR~=wEkq~D?yY75uzU8 zV?@9CSL`=hr^1~!=P!OU!yRJX@o}4A4<)Yo!>|~&=O)aK0ez%{=TkDHUv>WZmkraL zzLejbYaTed`9jgXnuVIltiK~et1MyBFbk)wROqP(pFX4ix2)y9u>4jf-^~Y9gGLDL z?j@w63;$+Cy}518wsep5iAM|=TdU`*{a)u@*5?_&^LhGkQid~LbgHVfUCQV2N?GC+ z%KC(4LD+PAwE#vUPy<1Qj@PBHG?Wiv75QV9G5iGYZslIQ^6;vg1=mht<^V>7Qp6l% z4qo|XgTZBR1w7|U%rh#5--pU!D?6x7aRCr4Kp+L=SRE9wA*N!La{`1C`?*)>Ex${H zOPxIY&U{_GRx%rd8~YY#o`~ny|KPll^LyFTykh@PU^_ql&v>Z@TMG#p z^Wx#N&cX&_d0v&q*SS-;r7A-$WOG1+SDtEqN@;;IXS6$O+lL|n1~}Q0Rz8c7J*${*zRj&cw;(1or_Aj|J9G78c-ghGMW>? zQWY2>Egc^7ALncIlT>G?Lxys5NlD6L=3M!{ z1(nk+p&8OCh&#+vA>)4khtS;ID?9MajnW2(dk-3@do|gq-OM)NQl`e!x?PYf#Ly^g zXn8Q8b9xlNG(2qz+D^SO?XM8686V-cK&uKB8--Qc;k6*9w_4<@wKMe>J=-QhRY_Y{ z3d6XSB6W|>7GPGr!8sZty~uEIq>5qh*DZTfek8*49}rwc zgR8{O+;!#%G&Q?7Q(Gv>=c`(*B8umA2(SrV;69JtXH?!H8dx zt{3BgA%6o-L?q=<<*vRppdF*&__q2knrv%t&sk0l#>o)k+!2(xAq3h)YP_4awYkH5 zWGP>q4aBt1!dPZsViXMU$~9mgYB(FFG%%e16sdb{A9`tEz+h;S=@KTQmB<(T%a8sy zpl3ByPT`6!mUi;RM8DK9g0N)@@Cj~AsxLMDc=5n%^gWyQEJmS_9 z5pig;!nAbu5wvxmV*hdE*14D?$b(U*u{k;??h?WP-* z2ytI?G~PR<{h^O)bo2eDJk;Y%0DD}Rr(qMqzb^|WD?-Qt-Y=}zEm7t6R_U~XA065d3KX+}bcaux2iLu$PC7_Y#dMUKB4*}%s8BsB zVMV8Mw9!yw^SAd~wk=e$*-p_CiP8z4s<%NZo%Y3~eufBh*>7b3Rbr00b*vIYAcCM< zd!)<_PFiXrDKlX7O$-x@B&+S_c5f*=^5dnWfyoBAW2JW?omzw*fh06dO3IL(A%OsN z;bq@n$u~x`_pR`MuaVIXMH$(P<2`SIl?`>O@w36Z;fF?a(S1`DDEd|sE4ut{1yZ8R zgV^~@&)omwn}?R9#VPq25KRKGN2P@K2@aD8jn3U}2$HB2mSBKmk7)v!%&20YQSHLv z&x;8uus-kqX>GX;&phSzK)mSixUDk z=T6S0hR=xdsxb$_nAq!3H+$(%J&LNKPOc;9&64{JuEzQmiKQ6AqtQxphczmHrS7Y! z!s}-|$jcg~IF~DY%Q{E%(A*oq!O~?Nefj-ek%+P7rWIBBl2i?1@R2jV-{M7=@}O

Sa#`_n9^v9hr#Xl4g_Cyf;3U0>=g%SjsZ2~7eR2<>Pld~w=-UC=hGvKz zSMi}&`gJ>@Ryo$*JklZf#Ztv0&*LsiEo{$6MxARa+Jtc(QPVV|M9{54jpYOWM+DP` zb%Np@|BJN|qY3w0DuWMfObNmyK$%(uf)aVTfszdjadptN5soKZuo?G+OW$F*o6g{g zTATi`8<`toN|DFtjp7`#@`yW@o2h9e?B{#cX8Aa^v1U6V#22CJfOPYoyqQ-$UOS@6 zV|g5`2v}arg+cgj_XDQQLCsr#(Y4Wuft${y=TFi($@kiJs zgXT+t@JPdl-N`NPeAiU_`j?Y8CN+<+;%U$6Sg5PY`afZzW-nEN2hXu_CJF7xc2IZ^ zh*1wLTYT`;L@UoPd7ThU1BfBHHxFakutc-=W$8NNlE=$UN4vMqu-SbAs!xhmIb{7` zD(tC=mp%s`SeE(tdM{a~_k#KmKT}<9B^IQODk>B~Xdpf%vpT>;6}@&xcYl_=KTk6e z2qkdBk1F_RWAF~NQB&1fn1R(Rm=Bt>fYl|L`YkkhYw&2nt5ect5&Ap^0LRWx*_vQ0 z=8r=@A&-xhlVC5vKs)yl@io31x@u>xx7I5n+Uj5lM3!ZgLS!)Jb& z>WNS-N9;%FPstA#*$|AqTR#c4%Ea4SAc{U}3;yTs0sf~G&KJH$Gfteg)kiwHO)3g+ ze*6S&O$#3|+1i;w>vdln70xeGkBLkCdJC8Pdb|(Su`(|$*>(I6#(Hb3i12u${=9WA zjxPBoLMjQwGB}Zj`J2VZp%7l^4EWcTYF1Ifx!)6-N4#&(1*m(qGUzp6TmJ^YJcl+U zAi4(a25fm}nfVMw&0a6R*z$oZihv(JS@lWB_p4d#roJG#9^TS>yZWkScCt>$B{X9{ z@#?){d7EjDTskox2m$EV1U1v}iUV-4RWUK=2c}B0S64r1fHNnjI6EU}PZz65QaPi^Z zYfI>wYYV9xo`oM_z45ZmqIx8kKX>bT%z#KqQay}M@{s1J$H7mcgcN%fOo=y1>n&(H zhceak}3 zJYCw`>`_ChQc00S(5 zxqOoT805?{{;71k8mz=g z$>oV|2`Ey6&USpo{(RG$E*kbXBQM$B;FsTK7UZw^#V*ub#!zrA0L6Hxy-JXWA={!~ zY6ba0i{}`&{7-T&q%v!!OqFiQjPjlU*8w0l!^oFr>z$6!xkK+?dkNc_=fyWn# zuYI1T25}UWPXm>{%0gUuXt7EFK$N_Wcn=$|!Jm4i!V0IVVFKUTVN7zM*jfE?X}(2( z5EYO?FMu+m2mNjPKJIrvV_;v(wM#BVS3$#SerZL6&MlO)*|;|fT+k(-0T(iTuWpQg zzH4aAN0Z4G)1hS3*&l>5W7dPwB;LRZ2}Ig= zdp|1{izszKt0rCme7#kLZ1Euqk&{^>SrBA5+|a+fLW%ez1A|HZi>%_&X7kQ4t9KXv zjQ&ZoI1Pj9%;wsL`3J$n&Vp)i7@2C}stIus2g37Xx5Al(+60wpfWh*DiznwvaV8rA zQak7Bt1N;^{r_r*wBhouU%r>w;gDBW`{}Z0f zW|XQcj%Dks2^u}YyA#UZAP1F??7lRGlf>24fr~M;IK?{ct9(I-bXP==EH+X=OKz7r z{M@WKE+eM~6{4{UR`jWlJ{U$3EYr-qIPPn(i3rxz&DbDn=p%h+t-)jO<*SC)9b0E- zbG}`0=AWoj-&7WLYe|zf5?6(ty=)Pc9Qw+UWd5c1hB;YR7wJgExmX^?Ec)%RL^P*O~J!BsbwX%kujHGntz{x zQ`>G3G7?#JcF=OW{I+-FV6v+^89K~xiD&zdDQ!m|8U7l?e{04kG={a+!KS_#T#~t{kQkSxiwKT@$NEcgy6ZzUfNHr=IXMkMQJcsSpsLW<#%E

    6*8v&@guyL)GsGE9Z zHdssRkN?vv?9hC}>P|wKCc*;HRi~q(OJl~8jYRk{{Y%NG`-WazIXu9#Z7i1`shM*o zR_m)Sa%|V@nVyh9mfCRY=UnvDk_Nt{lrt$1zT3-!Vmbgh1E-B9pv`lz&uxcH&kyUAC!*DFC;F;`Zcowg+kvQ2NJ}9%LP9_ z=zH6D+RYZN1TBl9_GcceDKriSFL&;ly^x7_mqA)A zsL#Nwni+g=yzGDpyuLcQTKQ9BGD)Q#Tcl;Qy_sn$B#YvNe$*J;Wa0K&k`}lV+URJ9 zF=66Pvl@bVcTBBwW(e$G9uurDmyFZAevWHIBbV72Q)-dmN<+w_mHRmiRK za!Qa-pK8#n&9u*YPL%9!TLpk)skT3H;!dYH+xe8Q&D~m}$CV{sh1DOo8FaYS-!detzinc{Z2hkH-04`p)v8+HQjR$UkvVcq zj(D2^?FlxU@@t~3XR3`JRyf<|gR-c!MSvzH%O>g1Xh7Wui-ZH0@R0r~%zUPoP!>Y( zitXn*i+L6cm`_ADQBnuYcBEpL43y0lThpA)K025q)!#$!v>L4~I(1H@iWG@-dm|A7 zYcHJqOrvN$f@XrjKQ}0noH4#hQXb#4#kh~C)(Az#I;#DgBy9g62|~fHKZ_)Je#IZ% zO&9H}$w66VcfOa9wRyjPmL_0lZXB9#&a;G|gR7}kgjKsyq6}E} znu-1d6V@Z(qdC8!Lue=|XH7l5F+*FfIOm9>ObX(P$HVEbCP@#skRU-G<;u(8w}(~1 zP@pLpT|1a-)8H|;X2qhwi7OoS#nC3YW^^#dS6Y6?q&AH)`l7q2-aZQ;xOfrL8C&T zZ4{v%-FGSo?x5F2$*kxIm3i%)n7L%H39)mCBwxLr{1WRNzD2v03zZc<4TyOaK78ywTfS0`dFmdVjONQQ#b}eiB5&9k1VbyQ8OCvYXEn$ zlI3-owTy=dWfdcZ4_1CNAqcH->RxZZ4~arn>9{CFT*x&3MrNl$He#14zGh7@hb2On zYK!U>isa>k&#eLcIuMH(cu;^JOHU$rz;dJ_8gikMxgB5VtJotsfwjT}JySV(c)U$OBv(gwU(H_jC@y2QZ)*0;xiMNG zaFs|X<=bOg5t!jt{9Lm2!~5X6isvJEc9M&d)7JG)$4h?EMLF@QLb4tX z1*omXhvoZ{)T*34W{-y!uAxK0(QeyoX30<1RTWFK?PO7~(Wrku@Crl_NEo}wjdry( zJXFW#H0r9DJHIZ|JP{Xak1?1!eS}`qQ$l+3i-Lx2pp0jE?H2zjq<*jckYx9=dtWxaKI4SI(;3;3-aF3*hky zokykZed}#s*{(iP4rJT6HIZzp?pwoR;xzIC%A#`Pz$YMJ+K}FH?2>0H!oRZ6$;p}A z!OXBxl?3I9v>W78xf(o)?yhNkV8AK=?+wg$K6sRy0jEL<#+=f+@pOGL&9(BFT#}yJ ziHn7bH&kxvw)VH9BlOLm3J}~B8WpJ^L%4FOct9Gn3pBgQ3OFxcd4@c$`9cpo^7I-T zh7G}m#5*~+WsoPBUrnbUW zz#Z3as#1^-2q=X2(YD-h&X2;&+F(g%qdySVf}L~3NMpsTd;VUSJyQ~J6P!Sk8~Itg z_PN8>>Mys*(ZG5qZAeOpd8i_;x!san02+N7QH4-t8W9x8z9R+eZrKK?-txf+Bu#bW z>G<1K!WfjVP@Mn*JdHQbG{@mJGP=z92+L~H#v*I6eaH=IDK*-n@`0{q8kZEF44-&_ z6A>t11gF4@V{nISzPB%VJ8zfT>nur>!3cb_- z-L16985rA=#&djC_h5nT<4hHXsxpVj^gT!lP{&xd`L7rpU_EDFgu{} zQQgWPhwtUA+TKBurMuxBVW{@gk*N3)rJ^b6Dd4j>S{kCp=(}2CpJ|3Ai%m2rDOK_?>Cz7CXCir?Q@P$XnE#OQBEnj?-$5z z8T-bfIL=cf0taS%8d*DhP%HAtgjVFc3S}P1X&)_bi_6UGAEwR^9z+c5^QYR6jL*`M ze{lDg6Y5xkRj(FM0g2&)^=XCTR<>(Sya zE`Cd`R@RlxqG+O%YT+Lh>Vr+|mfn=KUnpr$p`p{P$X5<1x^R2ZwACq*HgaUZW?qyu zb8&-;?qJ@Fb{ae}7M#=d-h0Ip8pA&Xea2(x>_{uXDJHcE)jCGFT~>M)wi6J2f%dU( zgS6ZZCGTVo*!bR)Dtml+`pzpKRJ$z%H6Dpi3E_LC67~D3LK-?=?axH6<)goKec{1M zo3j1Kph^+r$VaaNL_ZI5muhP!(Aw@$-J8bw8YhFf@Erdu_9wOoGD%(scm)5jW&Lv{U0JtM&HUEQublU(#5EaT^V>LdO1WR-}GFb7cA--_e2bEv3mvJ zIJzdKbYgyvqd7K5;EsIhVO2r%P)&EJE&Tx&4pvf*b^-V<^94ISVq=_QTWh~ELr}t> zQ3*m4Fo!`@2rPPvO8?K<3!fmbIUa|G(}3L<#?G4j!qtPt{(=}yw$aE|hr&>-;-#-g z9l#y$gF6vyo%V;VAI5%{U~mGL4lMtUt8+Dk2)g@@KR zP0m>*+2^{63m8Xxe$b;g91xUK-8~oWyq4O2tQS?_)Qo_q&MA@!Zw`R-+)vr8vkL0L zuic!BqL+SPJeX*VG5QJfj*dE>Mg_;EdjBazGliXoN)w=XIHyp&s6p%fE-uw)<*%Kh_*BkF zhG(PRH5y69XPU8PNx7UOhQ~G*QuTVEu*i4GEnrbNPT?V8Gug~uWsO0NgDa<+VaDDq z1#~C47^b3wDmMd?kb0JE9Rb<(mhD$Bb_ph@mx;zo&+RNS9cfCAHuisv^=z67iTpoI zywnt@0B-{39O`axeMIL>z0)lUwihyNnSYGIdbyQWp&V+g8~=rSAc`0|cn_V?I=s^b zi_fQP+c4>~k-PS3TYz1}5`_#K8Vr2Vscq$~^v1&2x%K zK(sIQ@y^vGIR|q?>=r8!$>Y9(@n9dQh+5?uUFPRy%UF(XfuyAzB!B3A{QSZ{zL(VUwA7JtSTHC+E%vB1s@ z1U4@3N;ylpbRG=HZYD%@<>*lYs{@CVYe#xN1Ua>c8;2ep#x&Ya%iFt)=tE`WQP}i* zhLQB4v~nC}cCAWQ|Eu{usU|J09?ToUIZBlXJYq2NI-!bI!9=4%9bwDXqR&dEbd|iZ z6xCM|4@o)ZhI+qLcwzB*Kw&>YnEzF1O@_t?SC(#@Wih!0Ejs^nf0-U4v-Y5m#H6pF zHw<6b0vQ%XKfXau^Raac{G3;Qp<`peO*aL4=O$Z(d`n>|tx7a1iOlM^CMJ9~39L!F zCr(YTFP16fkYRO+ft7Oq+`b*?VEB@=o|B}z6mjSnj+o)ph8v@!t&wA=F!qf^v)GkI z?~QD}K?DIy$pbClIHDqC8XA%o-GmIYQvOWV+0jK+mAh4f4u(lb%cGGzu z@1Hg_+fJks;FR{_d8q`+-%0%hj{N|*G#1jH(vOiei24K_%_`AgN2^ZNqh8SX1qB`N z%z(`+Ks7ajB=b3e$`W0cLjpj6UICKbGC!7<3u*l+S)d)2+S}2U`nmr?IAJU8%x=;i z#dd43LG+$XGA4O@=MRCRZ8+#ENW|>E*ll?e_sTkf0ZTmB9gDN6_NHalorbB2?6hJ2 zL!dNBj$>utJGrKl=)w1&DR1o?(TOr)TUy0EjFg&BgeTBXcS4BjGR|rjpr#*PtYG zXVk{GbaFe(WJtOv&V;OY|M`a6Q3n7@#Knca&89Q;*;APfhX=}HdWKJ*0OPhnAXuu1 zLm47I-!IVn`t8b;1bI#r%N0MD*YO0Dx!SfKkL_eg;%0pmUxQOpTf1lvwecqu1 z3#~RlMdF*e1da#2uZUp{?s%~=2B(0BuUCkzOWA?2@%n*>wKPaG3G{9VdjYHGl>TrJ z1JLcs&ZWBg>X07?g4FQ`%F^pLzGx$VwTek7Iptfl2_fioQ&bannDSqnLO#F2vJhRI z)ov#<`|XU~&;<&T`1kC?HTr6il3-_CK3PD3C~iQZQ3vZifcqZV(x;5+)MdL1M!|(c z`#|doeOtWVd+6XuaaZiA-fm~Av%Q(4Y#x3V80?%o$o_6p{kg3vMB}^u)d`s>lBY{O z!wMf}N|#7ge&`&OCW>Cr>>-HcTzJ|A_JBX3L0!9G5+Lw>wHkUA`h7+&d zNsVoo0rsD9MpO5>Ov!m!2&h)E`4hq5A$&~uo}ckvor##P#&vAbYgM5|lB0^{(S8i6 z%=o>%u=1jT^_%my?+( zIB#Ln5Q{cXyTre5_cP-0_2s#k=Wn>AwCOI@eI2kH}nfV6> zgqwl;`)}nuPD?3vF$3Y|djXw-Ut)mbz;;p+H>J%d^dAe3=%21oud^9mvHo~Lu34HjE0SCBeUM7V zFd8t2HFMDAF1n$nv^*oBh@biH;P}mDwm)fZ*MUl3j|SH6c(+=g33q7!_s=lNXRI&> zNPHvsn;ev{IKO?=6v9nk8_FxL&a_~I!rPprnnzd^=Q<_wplFJ~ah zE-b2|M&|m=(UzNL?BwJ27*mw}S$$6%63sGBiY0mlD6FBfS+u`hGiXWA6TcCC>5Y+w zznlU+Xo^e^A$?yB=i#QT3w)Oj7o4kB9hi;7nlXP*3DKWM?wDQ}x&o(@EGFQjA>}ic zqy*r!d;J_Lgq216BZ^J+$ALzq>WEk?`>Lx*OR>OM`Z2OLeun=ZxHh1#;EoVN?IDNV z;=D}H;gy`|^;enwQ!Ef+G$%*PJB~m|#!SX!aoT66FGGS;l;paxD3=rQ^g0Ul?_R;c zaL^mL+(*%tm_1@?WE`}F4=ukf*&?A>xu6cmXBQX9IsHqo1KNcK4LY9bK|Th^=SoKz z)+#}i1bHIC?bOEK7!{h~?o*aCEYkyenDDQF!<>bNF=R<9J`a(5%TgIf3?I66}cIfxv6qq)$~_T+j_gU;xjItKXP`XT-OdI za>@)lJbwWo(-=h5^J5ki*A_a<*dK6`*D#-gO^`_T!;Rm-*h>nK#Zq>1Ame!7bgA!# zZbJi>k&%)%v}g&d-mQ=DcykW@c}eTSn(-C5qfC-eo4_|*U9}PO86H#7CAuiWKvFFyX zH(qz_@OsdRbp*b{Dp=OSPWHj1_a5ptpIg#wdaCPJ%WbN`(k8}Y2PI#R-qrmxxGF6Z zx|N`OtE3r2SN*m32f z4|TflID8aC;Gf+ps*2J?-#?0noYRE`Qz|%fQ7b7w!-@*R=99LFd;-2;Aa@s-ymlNJ zs$lSfsEBNY^_!DUx&OA|&!m=s%+lpE5w?$@m`%zOARSt;gd96-bqa!|WB-9DGkC!_ zFGU_`x5TsEmBsb*2QWJqOiDyB@~H%5?PGGSQ=|JQIA5pFkoic0OYY>Knj%)bHmMtP-T8 zwgv8#L+qWdskq@OqId>vhx712F8}L}gniTie zfA&u^eHr4P{#lUTj;&#-r15E^2MbTb4eVx^-{n{cWH{Q-0>fQvS1}&cy{(P>(3CEH z>-r;QjX=jfl;;7=u!)_GvCjv*Qctwz={f0-J;^UevlTI|02l`l@D|V? z)}G?5ug2%k95w&oG|6wHBifF9mC@#_BI_u9Ew_?v?AbHA1+Comwo_Se)?+(RxQVYfeo`f&ALfA2 z<~!|gxO(?f@|`Cvs4{}ylA9`iY~mvnnXq&+Co{tj9=(41nV0a#>VUGaE8k-^qrY-4 zYa=w+k{`7bvWqARd@F%teA?WV11WEXegtkCT=-46f@|+U57tYzeFA`BDfY!KtyZAVe%a(;70P;&AR>Wx%1bb_*rx#lxQz4% z@tge+p7koFxR9+o1O!`n@{(~C!=Rzbdx^?9KPsD!@~z{PNq!R1A4nIIBjh7V=t6TD zI(}w8(@@vqQdbh2rj?Cb9_nlaGP-*B?fAxC`+I(2`mu%7O^ET zM#T->hRDx@7KD}M$MuM+27AG*e=;GDmSyD72>BX6@t52rOe>>jR(ne*2O<{~{opvY zcci@hJ8@T}mX}uktt-y!s#!9*Ew_wn(`@HQbknyI&Fz_J(idFyJkOQiEJ;46WPGaZp*TXm#xk<4hDWrkOaXl=%*?CnBgn82(rbuONS zs&J?Z9IFhqm?$#JDX85q1*fFmk;w95s(KmIplz}eo6PhxF{T;y+>fT}f`u{T=fzU^ zUYN?F{cYZG&6+>MmwDn2?RIZ7hhDDPY7{^rFJocSdA)Jtv*pLrgYctZCMALHurZ{C z;bt9<4WBO~qfSr2q6-vi2giL=prf(`pu}WwBfXk9(SZJ!=c9ZIYSTE|<~eYovV*HH zGe#pnQ@={?aXSd9y=GyupzOLG$l8-gZ@Aev3G^T(+pLe=r47+F647`JXqT%_JHD25c%?B00hAT;e zVdlk_2LZp+Z)ZJq`=gZSil8T@KkpfzUHv@>#zQDRl#@Dx@q6i9cL_3`+lr0J$4IDP zjBzd-rWfa6<6G$4ewir^8Qe4SqjRq7-kJU!gp)N`{Zq+(Vm>ZB?fK!ttL^q3hKEg9i@-9%rBBnddFfw`5KR6Qeyo6GA|v>Hht#Z zB9IG}W3=lz$T8c%xQaIdauGh|WN{m!ln-XQ7>}uC+($%rBidYqklY&@ro(2W?#Ul! zaT7otByM&aG|_k5p=|DQwpby9p&kz`nEbJT!e+as0`=%?BV))-?Iu>zAgj;>+gj-u z;NeXB>Ty1vX@5n1$|Ty5CDpz=9a3u!-J>Nrq+QQhyLG_8KoBK>(oMJyc_BIB!U?LHRHu#|xQ-L7w<0 zEyOm%a(UCz>K+&fd znr2_LoLlYp(rVeYN5Jwjey2cs>e&~29J934kRBBDEO_0!f~l<8$I5IPDc~nlBN9-i zOh!UABj3~XQ?hnmNAt;mDD>rLnzRg`M-{2bzfSvgyYhY1yV z2^~Wisq6h^!0a)DOT9Y^pf%B=z9g8V+rV_>C9z&C7JMcY`LWX9K64?3*{q87h4&e@ zzw}2vaQtY2)e}tleWc(blA`) zzq#WeQy)tNI|<5NaD!V0&PO%W(U!XqnRn`G_NHjG{)_3@|4@piWMvXw+}Zcm)R(vt z#MT+)Vsj!9!hfyRB2z!d*cSAmF+22TaOW|q3zbPyvO8EW-_GvAJkSHPCIL70jEHcG zs_@hQQsj6?Jte>hd+$$Gn0h7KhS;y6p5pK3Pt40QROZ_o$`3tEtoFQtVH8>k5hIS7K@M zo7Ho3iSac*|2x)v-DyObBz#{UN_~dJ@OBS8F~fsAqKEdCEENNz3*}QdfRG(kVV4(t zw`?Igrkpsa;%U2t#CVK);65p|053q$zpSic zpRA7~iXNqaF9hJpI&J@1(Zv`ZgopfL@(ZAFv(2UwV_H!PJ4;xLeW{&{DgxD<9F6=% zfzC)nP1EcTHm4uS{Bl3oS|dG@(VbGE@6F*S?8^AXR;Uv$ijRGbUh$LaArqPKiH>6! zKSJwQK}S8Pe5lx*LgGw=GPQ9f(ZdOOfa&tP=%q#2$q~z2bfFrVj!vEokihtWYlg7U zVR7IRw`s$=^Fnq_*v%N(?WsM-U%Ajy=0t6(72?1PLM7;nV zUgk4>b)1BxYjma#-srWH8MX~{DE`K54Ajw=l=ZSExYFINoBsk>H#{v3Y@lR9G$8P& zyl@cP$~^Joe>D^&ww-3u!@<=d%t+(8R}RQDfqdz`pa^TPJI)ZpyaA5y8Pe8RRi7q* zdcv6RPTkwyrZ41-N~f4;nGD#fq2Cd;EYc z(mAd^-&EHZK|`wXKQJc`fMF$kLth?AJ^(T%XoE*LwCs(xXO*<8=Z0TLc|w%XwhKDc zbP}u=63%8&<+DAJi~QpK$z1ds(Zjm+JwqR#-(SpPqaV6kaR1~_{^Ln^Snt8?h9WHi znG%nQUIE*Yq6IJB6T}?JCFLL6(tH|J)3tJwu7jZfBV-Nz15olI*s=+rJV5f_5OD#B zQ8MFZv`2NHLXnhn*z3x%12n+KcbfwAkrecHg{pj5Inf1@Kjo$CMBMh5IrfTk@~|k> zlpyjV(_roq0VUJiLT)dkmhyLs%i=IK(9vP321BEAaMD!$rgi3?U>Wb**y)Xgh+=jB zAs2PxRc6F2!(K!q@B3Mfjz$JKN=Uf~*>Q(oAVvdzSr;-CXBpKPDp!YDt91%D$Qp^#fRdl*o)nzCl3mayw zK3&AF_6Q9u$?>%Drm+G1s{3Vo>!cTf39R|<|I9{td)55B4`S-p{a=to>u$rB@Fk`Q zJr%V0{Is$rhugBtGA{`TjurC0;S(^g1ID>$qKh`X%N%;bByIrUbl;+-{(T=?2EvQW zg7mBUfM+x2ev5#_I!kU&ZZ}s?w&U0O;sHMoZ=xo8EgV14hVVVu=aB)|FZB(4eXPY9 zu>fGTCdFps~<%Vae)QBXgm86z&drkQ~X%8DV(COKgMZa2SzP&eLywsAcPBQv|d~+UkvJ&8cVd)=$ZoX49r-XD(6*BYyH6G zj!-Q5+jb!hVp&#MxS0gTk|PxgYlX3t%T25IHorp@evShy zJyK3WJLYXY@dZ9>$#H!Wu@$=EJ~^z1Nrg+4TZMk6^&ZUbOO0S_Be=l%7oyaN*A^aj zx#B7JxZIt^9dYzs}2< z!z9L;onv#&u9fj1InV#8aAT*r*2)l>EQ0-xq@!LGRD3HVR#XPQWwjyK<8os8{<6z5 zb2QvfrAa#&2SjX_e$^(x6Lc(^ispTwkkY--O<%li@_ieIb-Y9yo-7}vc3thtGUBV& zgIQhto`Wm845>&UX>fss9%&?^pz2YOxOGs# z{g5&ilE+-UCS(>6XVHc8#j8uiTJ1hdju0#BNV3qjJ>+;?5j8?xw|a1{5a@(7r)YXI zJBLD!9^dEtKkB#{mO5;|h(=YLT+@Er$Zc}ZE*4CH6*Lu#tem70o|_laO$AnUbE)iU z&uVm|>so`tcux6IU3K!(v1i*kgQbBDPkDlYg~$80m+7qU<;2}8%$jT6=;x_`t}I7V zM%t^Bkwgq0H)`K`)o!=$9m6$jhTEyDrPxB+koZ%7C`nt>EJ1MiiLxk>-Xksc{#oCw zi49IzfZnQhA$D2(OrpYx=mhV7SGff7v72Tg-Ql9Vw=DG;0-!QCL@eJ*NaP3axK~Eq z(IgNbyMlRl{~ha(w+5trJym_7p;t6^1c57qC-gIxliv;aB{}`o3tjWA7gt+<`8Mih zXHDA`EpM1e)^^iAj(oM@i!_)0BXmM+KXc46y}~0R1JJH8mwIL$Id8TLPzx0l$ zMAXVhMSz3!e)%U%n5n>&_T%*6S;f16^VQ{)t7q=~hGbaKU-Nmv)CeOvwMQ&_srAVk zFkjU&;b#-Mk{&v#VO*^OX+VjweA}wEVq>Hho0Xey>pT5IaT>@+4b26Cz zZ4~OA_c<)9!cj^!rDS*%OJ_nvX9gU<43K$bj-1@DW zf@NA4T;DmlrsHA%y?;o(!zR@;rD~&TmTBo&!YmpRGhayZfXgoZ&({f0OL{yc~M!Gj)F1Vk)4L6|etC!RgE zlnShgR>jWSP>ZK)sO?-UBav6P;}?h6YhMDZ1cZJD4Nud_Tc$>|%rvHikIaOflxFI_ zuo!V*n>pUj)Ufx_S2BBdXK{*7r8h}FMEA0h7D?(+AhV6WxtB4(Ld!dWSbp&i1A!s)ae*w+a*@jIjvfvz4JR>?WLwd*bv z73dp`LGZZcK+QWD1Lpba3&mFV)+Fm&n!+`yQFuHys4(a(jGDpw*DA>$$^&_(9*Z%~ zK=I!6{+@Cwse05n6-eUYw6s%$JjrAOe%yip%B^Wkm|+5wL{#FHri!_^i+wnA#dHH{M3$(bB2}3PzlOH@OM*XRpL06fQ1}Phrud&Z?q)#@~dNzzs!EFt2uJt zx;rCbpjfhs61%F7A$5pVq)IqCN5QzMvc28EwRYKV{usus)5A-rhewppB%Q3qpt0s^MO+2cMpuDlfb~9yF*|^t! zD%+5Nz-bd#c3h7LlZ(FH)g*3NEg=0@F?5W>Ta+ec2Shm*Bg_|Zko7vh(~P-X`UE~D2W zg=@_zfE54kp-Mco+P~{evgRhLEdu!{iruJ*sbPeTkwRbDms{=2mS(>)brttMO_`%0cCyeSc{A4zFx<&g5lVWYxf1DQoUr&=MkU-!lnNZbc zE;sTVW~rp#a6twxiV&{^?85_KgM+0smL;d2KG9o~Rppp2-jEq`csvQ_-Y4xo{i-t- z`)HKWuOKEau`zw)v`k{Dum?7oVXx+!F9;t<{ONCWa<3Pi&I8SwJRS3?Qo%Bk8w5sn@fa*YOwxRGStY}i#y2) z^W>MUK}9POao`_hcF)(v>QsjYT3b$U9THze__JOLJFt%Se9yz&l`%bCn~ zuBtj$WK}VVL5*w5nNj!r4FWtR_I_0-#9vzSkt&i`Z8ol;%;DhzZX^Mh zt_GtZT3sMq^jAh7)LqH5Fd6Lm?}2F9+Z;WRO)$oqplwk97jqkPSJ`8sSEU@!nNr8_ zSgKj1P4A*f6_ z^$i}E2Pz+^i$qdpkGEuDtP^->lbH+I_rvHUIrC?H*cPwe&OQ~e&Md;Trm+PFxD*Ye zT{$2&WvHLl=B&!iibC9mgXC*w7ry&rcrasdHuap)1RN%l5`PSa<=)$p`bu~O=!ay+ z8|nHYb8Q(Y=VOl2i*Uz<0bO3{EI+SmFnV1Bph+|p?RNdiZrDlGV2S>~vxa4^mxf>^ z)~Lc97QofGWL>UPu)n2(U9hSkl27OpN;omXd_Xbw-{OYnQ;kh~E3c+F_mQRf ztYOzWnsilmr~IJg(e=lLDsIQIH4neF4D3Nnq%Ie#uscek?abNxh4V@VoxM86iwZC@ zeHImx!9b4)I6|#VUIj*>f}p{tO*;{H)CtZOML~|9m|W;U*;+lVW7(vdwX|htVs;^E z)rxJ(cHL$mhw?Oh`WueLSq}-`C6_ zAim_$jHW&o)Sd24SMK2q+Ib2i$x)0aUxd!w-`nl!Mc0=80!M#?4lj|xiM`5GVYF-w|X(+Dm}QPgFFB~<;rXS_8*tx zjl7Esz;A&;y;3AU#~CnA1B2_BQR=M78Ra#}s|gb90gHf^?Y+qoAHLdo3^PH@j~K&3 zW2)(*j8I))fL~st6&O8L!-7)WD95&Em93f;wphw*QpX)ZVkoZS(ZM`fH|U7cPSb9k zi9ypYg>y%PlgEwWa~oS;2tJTsj;HtMPO;CDOFEAud_dg+e^GyhW&v#EtPFD=o&$Zd zmVFJ6Qnuxh-+i==JcQESu$13D7$5XAv9!cSHsK?vV18-V8*$L9Qj8HHnm5xkYj1W` z^=L*UGi)8rBh0ShuCj6QlqhuMfX)m})67)Rea`tNe@TFMPrp0aq~x7~ z0K^*sUPlE1wM>ulEM+bL5)f)kbr~Dv{bz;PY7890tCSNt-r$rd%A_lnl>IKByQ%}l zqOR@ysEh(cP<+*DQ7*Y-84ewx*9UR0W<0}@!+-6+PW)z$rJ0F|QsBF;xQlf;bjf{7 zlN?;tVHBNB=&$FjTW*s6D>q|rK&RfvFf{jxrB_S%71nK_*EJak8{ZQR3r6cUtH$gi zch3eVrxsmkXgS85U%x(NSwqW|qTJ*81R}k`c6$KSh)H9eNsqnU#JG1yqBKiwWU+Xg)$LTbQbRxTDJ9gO`)xc*dd`Ne?!2u- zH7_ZUEr(qhJUJ~O*Z8QMxJ9l_oIQ$&BRWbtb0P~F?!>mr%x69M{EHCx!7og9r|aRJ z)!Xcten^(ZIaRIs zJKB6Ch_-eUo})`MPz7V}(|6DXCjc;Gm58#mxoOpcv+EUjEXAI?Ap{=~Mj~PY(hSUv zqK`abvDLZ=kv8!Ws%Ccd4$^81s9g`5R@zO9w4>}TwA7X^uvq?MgW|eTo$4yi40|^@ z5Hs$tlq0Lj*y-kQ!BVawLn~opx;Ca}v5%29AKYmZE(mRXLTpe$Yag>u6};}NVZhuq zCyrAbGh-h~Q2ZA%`Jb_sj~g&zu`+TQ#Y8LrDB=`8OS6pSgAtZPtJeNxUV5pt3(FS1 zi{5=js8zs~td;uv>oLGLv>&uRa^+2LwV9wbT*ELmkRHx4X@Zna^vN%NmVaMzXpGomtIwuQJr z)EIQW3xY+f!GD`zkc(*vlH3)W6``fg5q4IgQhf>vxxMy*CYBOyG)+E$rqNHY$tBCc z>NNr=nTf#`9J9h;m$p_@W|Ai9ls!5%NH*p`M6ke!AfP4<<~v`QiT3vfU=CZzQ9eCy zl?V{5hdo$w$toK7xWl{E<-r|v)7scd#OL&Nq}&hqwU z#Up!$Pd1-S#0$xe$Stx)cUI5odj*cQM&YB3d8m5$sy$In#RkfMUqQJ01ClXqz*hf# zv70ha&TwtE8ylV+kg4JDKI+3*5@swUu5AdigjYqlh6|@uc<52-7oSksm$Pq5b1kdn z3;03lF#^3LF`-87th@gwktD5pNa!81Qg~A4#MBKHPk^6d$|m4+qnIxzRdxEtRmAc|?#N%*jM1qx` z5(c`S)JiH0^U_hG?f1&3@wA@DUrrpp3LFlu6GK@4HXtOW5fa(3N4q8kB>Aju=1N1S*i zxTU5=EXZ=H!{q*V9JA%{clPs#5Zv^CwBpa-6@TGPgiOg+`<4`)K*E9rt5!Y5m|oVA zaf>PW`{CXCqSnP&W-4zP&Kwplq5HexC#gv{Wts_C6WGM1$Dh%5y6)T^t__OAmZvS8 z82aSoY_r}LJLOVK)qAiS@hHrH0w#M}z02@J17p+D2Sl7UMqx}RhirRjgXz8Rpy-(k zt^lhQS9AU?(Z2x5EJ#@lKgeHZS^6>gsG@Kn@K@{>0 zcSGI~#Obu7618W1GW{1nlO@gMTOCTeYHnIN_rwc263+<#C>GfeRk6O>(7<*a=L zT?8wB0!pH?@Q(_SCI|&5EyWN~#^id``anAZv{4IWdgIY|3#5O5C4?V;64UppH=%>+mY_`Ob&<49B{biEH*jrdT<{uX} zy}*N#B!6z|UNVaR8b>E(cYiD%H(Cs?$6Qa#W|t54PI*q$O;((7==@xDV==`Jvy_p-=QTahP| zvuqG%uWK*K40+9#a!AY^##X9>esbiv`tX*SyEoKgq#=D2V8_Vtr{bu|T_I(SmdNQe z8P+JLla-=^uh7e7OcJghSB?7LiLVsTfn`!R32YQ#uf!WsfIrnq#{IlGyz0s2Ye(!V z4-rV+S1{Mw2P2ct5jHWfS(P5y8s!#n((^%}DKTH~c)Ih6W`rl5CyWcsjzc&o;kCRT!h)jkR~zNSjte=MZotK*ECOJk z{(YJB!ATINnh3(w^QkneE(=61g)f;uKxsT3 z3RP9pT?dRc^NbzI0a|tAnf=D0XVSwyg74I?xbu1loY@|*`D2mQt?h_qcH?)| zw!tXhGSJUiJ_8mP+?*Og_**hq1#b|@#U!JATNXy6e`?-gZA>>L=w3oEs$w5G;pf*^ z6_mOWka*B8-lsntP|cGGqW~VL+9zl31nvCeGQnHiAAR7^-X5ztS9AZX#(y&(Bv&H_ z=O7zCBn8lcq*+6F4&&Dqq-B4kWhLDx^KG&H%)ANiC;=n$+&|_RjXKWFJ4#wEPfB1^KtrkP;&EK3z=nKA6h%1Pap772ln$A=7tQ zEbf5A2MR!?NV>;$7EiDK4{`^gLKZz%mPbJ$zvHWI23<3#OfRcPXD4Fnu2yT9cO>`F zhAKe0MC-o&s%2?=~ZTgnMwDllsP$C`bwHm3XhXp z0yWu0`=&Flb|j8;(sgrLOWvW@TT>4w^;5;iW?bI@B}^XnzJ>kLmFa;iqx6$z1Gc7M z^o8R{PhwkPLQgdsV@+ApdMJmOCE4-gHN$L5_$!Z$=^`#lL}6CWPnRAWe4AX+ymKyf*OAbRsG-AnK%Fz)le^NGCErwc2-}~e! z`l0V~k-#wa3LcHPqYY)m!MuA=N9lgL@j=#YcH0(?kt~-0XgSwIjY9qQY4*nq?I%0q zV}fp}%kUij1gc@eFY2luiKPUlLlbjI<~9=P3=}LiUCLlAQq`r9X}j#`ZciGYli;3tAeg#=tTO4R=V z2CBT)eS5LqOd>qH+$`lw_c2}4A8~8QImSbl+DMb+l<`YX29qjM+30qG4fR>~p>F+J ztAP+koEG&PH(L3+-Vk|$iufD+2QF%4CBWe1-4cLWs^zff^ux|1_&rL}021^K#Att? zx>32i?(7>6dD>@S596P66eXU@C!b{nZst0!^?N|!mf%l+tMQ#ilulcRsHpg!%xv|H zvz^LNAO26x9`T1jk_6j;Gd*4B(#N+))paQRl*}C`GPrYp6NJ2N`=G)>+Y3vI zAJ%=4`v;y}Q3>x?Dx$Ajh3ntjpGChe9C(J!FyfwWgg_Yt zR|iD|wV49CbW(iaR7d;87fpgYtF7Ji?5(V*4hx;jrhUH}PJwT=TiGjNoH04FSfwGh zge_2jhvqkv#kP&Dc>v=Wx2)}g%o#fdvO$q|>es`5))#&|T0i-wMV{QP1dQw|kBGV}gu>gPj@HU)0!&`VMY`o00njNce?C1w566vn{5eiG>l7PKh zj~oLta%<{W^IgPu5lz~kV+Db%BGh^7vp;KX3>hv5)8q+Hg@TWlp4v^n!w(5t$l{Z0}Mk$1m`nS?YV5Uhfs;w6hbq_QO~6%q; zVpS=fv*!Z&C63F;iHZ2`P802$IlNxt6X7d1*dCkmM8#_aw6{}rH~E5Lm^jz+oQ#u< zom+rXsVrl9_>!&PV>b5MRXvLMt5zhz`qLQ86+r*`1@c|9O(ijdz!w0?3t#q^%8I8K z7zWS?km)>;Dc6+hI?1yUA&SVvq$Of}i(@#MlG6V@lC>iq9>9*|TIc11rCT)@DCIs} zRNGdLk|M=Rtz=pkD}gcUsD|kcZ7|`i7mB-|b2^M6^!f9Kd9rgnH3^r>Y0^rpJYsoS z{T`WZ9OKJBkhUXx-rt2nC&&0Pxm)XF?aaf)dF4Wl$I0g2FG!~@+_o7B+C)0m%C~^G zRZOqxKp_a~$guR-fF=)&37aP>A?j8{ZsK~gRa$qVaO9r+F-B7Kg)x8nW&1Oyq_%XS zyuqWxR)H{Ds5~1BvO&fj!J0ce>UhT298RjhFb-L7COPAB20$eSFn(MBaM#aKtXb~a z1XqyF^^e1r4=+|!C|;EqHKAr8A04`&C?|nOEg6qJ#=U%Bl%h)KJ!NOjz!or5@Q2b} zlf|-mi*XS(tfHK2EgBMFnZw7Z06W9tGo-{bm>Cf1B@JEEZ~AxA!Iz>OULC4vV+t^ux;*v-SR=?TG*o(1aP)e!!Xl)&#bVs5Kd^$b6q03N)8SIbhLwTQcfnm+meiBoDgxL6<|)QFl{Nn0+~bqAt44W z92(9+nKx$|cKPmJ>>8oNFk$^~DCd^yIdUYAfJu%)1!V)Hh3TPEqq3h|0bfDsbT zS^r+TWFDBm3Vdgv+~Ef{IxS$AB%M&*HD_(49 zKSx8opx^AXBJ4VLj2()9w05k}MFWL!JoXddWiX7QW>3L0mD1sT9#;Dssm}@6uiTt@!H0GG{A1tOB*bUG-1Du_A5G1y@#tg;~~=^R4F{7#`#$J z8030(6HcFZcgWFaKtFl?_e0k zhUov6k%#trPKc(M3FQpJ2huvJ+pDEXuxG2xJHkk%Z-rQ%g5mtch_^iROrL!p3k>^l zpT;z5HmO-A2{wQ?O(+=Cmq4(0ALx80yARdon|MZnBY^7c2Bx*HanG5cWHB!Xoq~lxx#B-Ah1e?dtgf zPOR;TpC;-Xvb~3J5TamAPf&ajrMIAq!%Wy?ngIjpz*8~>{*Ji1&*uA>F#xnhhk3@Q z2}$&@=*wT}ji-)an)WXR2%*rpezo}BcumSYUzPkS)MuRx7KjqknVby|5}So zuYL;7)er%B9HTLFhColl(lxI|rl1TRg}x6RhZ4DkI@x${O=Q-Jz@X<>TES9f=PyNsst z^l{zfjlz0CjOc~hB?J<-ltg9Z$8vQ{Mh%JmB%Do6%`i(>ovM}Cujn>^ja^CX7rYaO z2}HdX!toh_teQb6B!HEhFPMEDUC~Xl3b2Gg!E_%8 zm0WBx)TBPeg(5O&Cig6m`C$e1HITdgE_~UCw2#b;ly$5Ho8yXEkEqG8KhcFC!K=lj4^$cpb*)?@*ATxOSfQ)GU=^) zkWI+!wR7g{6K0~)2xoWhZ|@H~%vsYLzwj}S@Z(20aYF+##<*)e!TLFT zFgF+4KaWOjh=3&aB=gN)i`S9Aq|MEZ)1VR5_h~an-KAWXfW^zMT0*_6jEChR(gdJb^@V3PWj5W(D;JmfKh;d`>Lv?2*}GK=VuE(yISrWfr( zd8v`W){^cBtzXkyEQlW3dAgf~q6*sx`cl6Ud0ICPdiAtU5a18WxA6Y9Z}NX|PAi`h z)ehLSnnJLQ`O+x4e1A@N5yG%QEos8EC8~ZzglrGsTmB%|bW^t>)FU>B3gsNkI6C}$ zyq#eJVQPfsX~7=Nk@gl1zIYEO_9A{^D0yHy)37 z49cj@t}Y3@*r2cEaWeu%OimUDT@VF~g#ccl@~4e&6y91=L*;!ONTS1~cPM4%KGM*i?mhZgGN`EIKHAFP4Jj`9-&nTN}=A$sZyG?gi0?+vDA3=z^ITP<2y z=~QHTI{*6y)YEu@$aunIlN9?*?o4jSpvk%oA%|ktvhjDUJS9F$r#%3yn^p4O#J(Qt zPo4u}LGzu8DuCOwsK`;qh^6@cZnykPWr;3x<%W%qw8OG^6R8)qtD2^B)Y0T(kEJLh zogQ^ch@UO=7B{P#t8Vvlk_PvjDq5!)ZwToDSvU}}qcXEXcqcCpa4#?{+X|$9qltgM z_4{$mD!ceO(IE!g4Y04hm-N>v6_VL?a{mzm2SI2YD!`*@83%k3M%mAHh@KbC+f4fd z!qQkhmw1f{hIwHI8r8@Rb3Its&edeAr|C3pxLG7f5!rqa^doDc(4Q(I$;p?HAbpmn ztkGin>UN*j~9NM+`Jy?6$TUYXfiZe=y-tSY*fy zngvC=A7pY4C%%FK&p?K0mR6yu@ZQdcOy@=$R@siggvX|2$P0_1oZoxUW z#PV{k2vKFrHrPHg5ift< z8Fo4_eN3r zaSWr2dcwLk^zb-scY*l1KW4wl zWc$M1fbV+)m8@Q)iXjuOXtPx2&Ktc}7Hp=QGe_xsf9*jHqI`WRmj*O^Km&KagVN%a z9x?!@)Gb7vYd(*-K{i%cA1~q2k;C8<$qPR9YztR%^ff~*xp@GkmDM@jc{gKCyU z<@e6tL&Gawbm4ACEHTl+x%S8i`udJM|Q(!xjWVIxcAu z=D8FGMcG2H2-k^NQJij!F@&u-OoTdnve&RNLa2LLbn>dzu}0V-S~4)bOQEugCv&8C zIe`<$ro27+VXfHV9|*lb>pKD|cek=3gseqnT8PsX*)Kv?j$=JxgszG%O zW0P^yHUNK$ujuL$j{@A)r2Gz*ai1KU$@sxCPH!9=~X98Q#R2Am(b8&MDF zeKF4{1xU%GyQ+m~0N0G?FMZy66?3^M$6H7U>iSOA*;I?W&$FA zHN!Um8@O#K82tlZRK%P=EpX<16%^T)QWe2l1m~2!9jl5i6>r`Y0XcAQCS*9+obtoy zdc2Qm_<>ekevNfZSFAp!cuoM!%RP}EEge-5*)g&Hf@-F*y?Z-Rv_!7(ctv}JXG3rz ztQwc=Q5^|Q7uA)cB%|OjS*_ouGU#`0NSqlk0AESQf{7(r3>drGVbBh#q+*nEiZ}Wi zzApV}G=lGG1Xi@paSxrOIi%kOWQESUm$D-%ygHzgrd=PLihg=HZOy6;%`Jm3qqJom zRyY$UN5I)>AK7mr^JosS8zyY86Wt#^39!gb=@xCt$F%a1PVB@h;l{n(1;)kQBevCI z`w3#~-VbG1ftWRsh6AO>f_RCL)l+?jnP`jG+UadnS%4+>A-r5tb-^`^!y|# zG)?d%*X{t$Up%}m0aMndyb{mFHwMgJyeve%JU>Ih>h_fkH?8Z3fl>%R(eBtINhXeB z!!q)o@~C|uqRy+-g)a|p(+~8?xYVgb;Uj>2l&sE3gH$YAS!5e!S^Q=Ntbh4!^*^W`*YM`>tI* z!xh27eCsqJYP>G@I)4EFtOavLz5#2$b#f&dCq*3C6F4oz?1T;# z5>{(!yijI3DJ=&iz&i$-rLAx$BC`fp2!RKOG2<$qGgemwz@2x(6F7=AG#!&iNzAxVd4p2|>3nM(xX|_E)k30>w2tGaTN%xlL_|x-jWi|_H+1v~~CylCYOTRLgf47=ew|j|px5wzMe@K^z z7JTrz@3ULI`{cTzWL3}g5ga%Xk*d-O06##$ziFw?r8S-Tx(wQ)7qm%Bp4u=3zgVxt zHK$u8br;jA@@L(BBth^m{e}v0GHQRZ62@WD}WQ8SQjVO z$2_61F*BH{{b);Qx={@9_~gEbP884QaZ&{R2V^PW7Z=|_ObqR?Po>?S;+XxRifGAW zO~IvK_k>~cLZM#bme9Ip`O0GXS2^f6T# zjk*-6WoQU$K0UJt!qqG)1+Wf#a#z=Ns{uf_74Amn<)_XBRlc)K)`l33KwRu~i$!CAib}X3*=)MYa7~&tjSws!n(Z}QR|TMGjx2SC z8$x9oUP<{Ux%r4d93_}nqXJ*9VPGvE8Z3>0h`UU5l>fKsSFh)zvZEkjFVT&7ycz{D zTwsH1Z1XWiQ|Er&r_fgTs@W4z2UJ=nhsP?HtTFR0NNlt*0Vdx%(9T%C~DvF zEu95G16d1Oq%cMWzJgiuZIdoo6N?$#;)96nzm>4P0?1onS^cRNt99ZrTbx-J0KkQK zO(Y2&|Ijoy%%95UPz)>-R6%8vHp&}R{J9~j!`Wv7_(A$MO=9WH-zIvvwQO@aR^3#5 z^2OnO5%#Amy^4u)Fe0Kw@mpB`9_1mHMVb1O0=Xj9E}Emb=v(E#eZXNkko^ayzh#Ys z9MS5C1*dbnoQu=27@TsX7n%jZs` zY@>YyM-?H{@jJu<0opUI_KG{xs%1^R2I3DUUdZaAh(53Y1n6Km|7{ zn>FMIfclXx*5ozG4FQKD!oj2~esP4!037~73$)BftEH9HsgeXtBsWbdorVl|G3FnG zkY~%{ARZIoKEZfk$kSHb;b`+yvb;xJR{|RP9@^=PXbu_HA~|at#jfMORdeZxtoQUe}AIeu8|MN zRYOpJdmp79vTj%6Z09bC>KIB`&26wIC8&7u&5%GC3kM3oEz*?n>%4-SY%IDk!Qa9l z5xfqCo=&)rO>ZuW=eK+5O;3qufkX@lxgsBn0=BJ{^r3d(nqr-2^;w%a?z3=`FtiEn zM36^a6cc{WmB^^0=M^1x%^p24do=}`$Qc^{Lb}9sBn|vG7sJO}F)7qv1OO`86u4cE zw(5E-aPKG=l5ZkMb>|SV=ojL%CNWkGl{<5wkm4tCveulYWI1F3Kf2Bz7N~RBq(wtRV2Mdy z&n@ONX>N4xvHRB08yh~X>7nGi%dd~#W#@bBH%rRAt96UnyTZ zJC6BOSTzP6mq4=~Z_rA%E>D`+i7v0`Y?!b75j{c~LZBbZNfnSb$w5{d@@?(1CkbPS zX3*>7YkmdGHUJQWYc2-cpI4B9}$6~D}orxKQ%XD&Z(!|$%#Z>R^G|naSxQJ3@up|2t z-&a<@K)3AO`bwQv`M>?|TxQ@x0|7R2vDJvH1KU^+Wi!#X@fHVol=irL>Cz{dG5 zIZ-|1~X3eFzS|*)IjDZ4k}3L9c2BQ4K`y?xre(BZTo~0UNFx#Z8MZNW?{; zPoSc;!h)1_PZI{^W*y|(jtk!4zH7aah+L+|asSALTMFasG z3=eGgscL68WuD-MDd`i%{sO@kjIu#Lv$!di#qr&IN_qY+4>3ms*Z+~Pn6XGfQFF!7 zc(w{h|1C{z!6C=X98j6HSmknZq|LF>MeC@SdU&;^)fwm6viGSTfd}@KK}G2R7B+Y- ztk4-D+Zm3o$Lu%d#V>8orkvR}YePKzzr@HZato4j&~VPbgQB8lqdCJ~msEXFAD`px zRngxD3YCbt2blrK47GGXEDd()9hi^&Y{;MXxQQ}Yn+{iJp4>}`oABJngKH&>a+F@A zSw=)HtS!m4;M4t>o-CJ@c2r0*g4W!*6=|xB@QU1Ca+Rd?<{*T{Fqe7i>enrGA|4@BtDdA)Zfj@#vEq-u>VLR+jkJ^0p9CKSF7GHKJX8X zo;dw~3n;lvJ^*GOB8S%x&iB}I-0gu<{2ogIHLZo?8O+zD*{kfmm#-acQ%%t_7;mTc zArFvac9|JzsHsjJ+|}_1D>^Gzq1X6{HHsE=&=jj6)C2Y-?DB<)kzcMy?fjAIROwMN zXBc1Q>S!-Bl`9&_gqWoVzV@t-9R-lfHP(b4$t2s%S|f?+rp}c=Nq5wZY=SF=DX3{o z@j@a=A9ei?ogW%S@YsR)l63FB6T#>^Fhx@lbPE~CH{BTLPO>)?H%@unUkv9c09Cx( z>kB>&P2F5UpO}G?P1Dj7l+*hLZm8)TMF+WL=rZLi>VsT6ZQb0^YKVbJkDd7h-Cymo z{0ZPdURQOE=H#W&6iJ7rVH-=a>wHVKCSiT_1o`J+3pxF`*$hs2|2a4eQL2_+Ie#^_ zT-G8rvZHKjB)6=Y!JDH(TwmdKC5v;!W1kWzMr(JurK8LmSTUV>>ojEbwocHe05r3S zyoT)^CqPl|ZBH#%@wxk*O=1HNJ3r~mhusi*aR6_{_4OodQaNe42*!d&-0GYSU92|g z)uzX7cy{w_G?l0M*~l13XLNw#5j9!({(_8(93${NaB-i&!=v?~jkM9dT+c(jaa=cL z+P{x2+9S&wghE`Q;qt?-`=E!p%ns)gR8BydL-KsI{&WqxN$OhM5ezcDt*k;hnU-bv zZn7ynMZUKGf(&kiqVxy5lcTrM+@&Hddk8f5sGmxQxPQ-wMTmcl`Hhk6TXwsk$1&cj zC?{SrNAJ&EJ?A&BVg%W_IigqPagOlxdmAD4Tx~yBR20n&63zX(qpHSIH@#Gqq;oKl zXj=UWfh0m$E2^1H*vZU&SADRZ;>k;4s9c0T=-sOR=5+cct!|fHTk;~RpK&HgRr`*k zs?8JIy8&lp>?wv|t?p#PdpCk?yD3C#vH(mxEPni)2oY*B#b&ZsShik|S$zZv@#t?r z8LMpVtb3+nL5281{3y7&`Ys?W4Ae_24^&r?Aq6jekc7?$ldZpDAEnG`U4MgtX_U`J7w2m-cm2ImuTGoeY@ z(Yn!8w$yfDt7yTvYC|=X-3e&0uS5Mxo307AlbNvD^iwch6UN-XI+_Wc%TA5O3Z=|{ zLb)i%%Nr*#->?b?7GE!eD(khlZG|1$3K>p)n5!Fc`rK9KX_-^#o_ZbdcTs;NDU`GF z-kCS=`#|iiN&Z|r8T8$XKjw#ePnn?+trtE5Vd^Y1nws#f(@B2f6KTc@?=q9@cywPY zQ37bgF4y`)c%>CY+bK+?To5A|f_+sfBs_8jI5&QdS`~fp*+&9ORr6O)yc+_eyaI{oUs!cK4cOn4rO<}=Yq0GBmh zWz_oJ>>IUl^?a$@c+7as_0HseTUpaK5GxbO5+dP{*o`6pQWzoY&;>D75)r6Flo50V zy-;2pJWuK*M~Oad6bD6k2X+l4-Cg&unl;2(c%V%|fM5Rq_&DPOLxUQ<=2~H{4j6)i zoUGkn3(0{cbet?<8Z??%OF0anO}rJfwTVW}G8|*TJ)1MNb936n?qgHyFMKCpps;(|Rr6Xc!=RS*JrWG8bg<_jmAO=QbR9WP>j3R3D%uPEEyG zs4+4!H)xjMcCr3I?&rk+xn{=hhXJhL3OH?t`TU< zLun(_ItPJMVaLuf?)by5AEP$<0JvsEZ@#8hUf6fI`;|DcK}0V#O@xTO-en~~G0Bvz z%AHbH5R3Cma`P}_wHP%efd5ky=@-GQ;3ZD>nNFdu$#{ibk~vA!U?shbza}GLqaX{( zXo!3*B%ij*35L)8zv^b6{{$Iv>9oB|0&NJT)0z0yFU{;xo$5l+V|If`ePUI8`>3#I zW!LPr9~DBc^~+a?Y-FX-^8K`KJ-9cR%|KZaSNU%=q z!I1MPL*|=Y#FB%6$D`KdyZNE7oXHY|AtOb&NTv`saxrJ}K$C1vgYZce(4w4}kP%mX ztQ4K)MU6e-@n2Udbk{eSE*OufeoED3seEBz+S3JQqEv;oOro+j*+4KyRE(DYcbJgk zr)CXA7IIJOe0!?0Z>9J@^Rt|h5qiWl_~kVRW(x88a5U@mmb$;EIS%LG_{K)S58V}_ z^)CdGv<#Veu6_qhm5}K5Mz~@V!Tz#pkb`BX4uRo1kx0w%%#|o9j%orOVI20~guWS; z?fT2!h!cTYho1K0d>uXtW`;K5`QOnEkr#8Lt)32T#2G=lX)4~?EVr1F;f9Y&x%}xp zy%bkV;NWL@<{*(;g)Ky5jYa&lWcj_aX{!&s9i>}K($PHQf8sfBjd1H4*4eU3#L*$0%xNL8u)hMNY4i=VhnP$~`uJPHKxI=qu z9~^HSZ$%b3x(~rP!=xn!y5xK~(@_@_Jec2V=uJ$~nvt>wn4kHo*0?kWIt>RdD)jHl zjAx`X*RZ0rjbM8UcO)}%COG!L@-K)$dPi1GXYtxN_zgJ^B7pux%|6|T&4#gbg&{Rg zqy(EOewzF-lv^9~vNgNE09@gB`;g+(jjYkqCP>@yIFZl?%UnRbn31^z z2f}}<6@+SqUNrP)@6>dPWuz`8&QP_G&o^ev=5)A(&Q&I+!dE=TrnAidJP@bM>gTd_ zNjTqCB%j}%bufeop2AH+tRrVj{W)_S+%2majMg+M3{fNg1V}NaD6shq!^|t=vgW8R zEtC7F{#yhMw;8zVBA~FbSABdex6M2sUDd271X{7v*aJ_rKo}G80v{?124AD`K(=CR z*7%eN|%w;^kc5nIwj+ zkPY3KCFGs8k&DoyB69!%X+RT*eM3;~fmvsLjsngZqs$m$2rFRYwRwDt`2`wd_lUgRE$L<7TWI*^Emrt`@WJ{_p$Ca9=3{F zDFLVV3ARZtNp7rM;1G&;1EZ;Du!@DBMQqxEM}T@*UC!ZOYkg>X`ZAqWKc7YP6wN9y z!4ml!q}=cC+zHyjaTF)9McK@?6PpG&IC=7cCS_>fygEE3zqF=7KOV8Hfz`KNmZ%P;M6N0 z&@JkC))3Z0Aki}GpVww~8_J0mos7&{A9DGpS~Bv^6Dwg?+UAanE=Em-inggH9X;Fn~%lCXhHI$ zIPrO(X$CD|Mz)tvDWeduc~-97HnlmiVx@MYO^(Bx>J_Gcz9^0O!29RQ0F(-t-VolQ zt{hv~>Z5&3F~%Hs7;Mvo-*0A^Avr}F^$}-3trIW!g^ww;dLst{BC!0PAY8y^SzB;O zP(J;r8nGxP+ipA~D}Wf-L>QXtL8KHeU|Ng&+zUXW|ES=GL@&3oWn(i}?kgxp4E=LA zZEf1RF$e+9JCOifV zHf}8m(?3+*P7g3+N`u4#^|{)8Mfg`-MK7JSWhF;x&fftm!wj!BHBoJ9Bct3}o!r~t zPX^A-x|)pLOaf0^YJuIQ`7%ufC0y+=KXgylmtuzTmJOB2qeQ zF$sC7gS894WJl>jPt(7rSS)yR)lv5*Kq>(r0VNvw?P523o5mh!L|)<(m4;>p<7Rr< zSQw#|(#r**R*whH?3H3p*;PENCmMn2H%Ctm#j(0eR&!o1#2*{RD>T;Ot?9$*t+g<) zUU& zO2wxUcxZy+@13el%zG6+bR|Vzgj82?-qDUSTlAKEC!Ap6OhZc%Ka39@CXE{8cY5Q@ z)jY-g+Lxx}ohO$RLz6&M*=#y5l6Wm&@9CXzat5#ZK{}ctff8@)ysDAQEJpC=1(6uX zhEG89Pa}F8;d%YDWL;wIj3_me4`urlmT+uCY@D;1K^JzM~s@&Kkn>^HRO~ zjZwKQff91Z80T${*_xI$s5e@L;}4^_yqW^7`FHPwjhFD)sfD^Qg{&1za~<@1D9x=@ zVW^IsQ!%nogou`Hug+zyA(B;0p;9r@7fZ{6#el*ZyThnsjc}05LFXHim*RgqIqW`# zhVGe49Bu|r&WGtpoEG+Mffkq^?2^`pD}$M26U*X*R%tYa2lvmw}%NT)c$n{6)_XAQ(ImtwrpdT|x z{q^)2(+s`hBOT*?2c<`5@1C3LOVZKB;ATJ$PdZT3Kzv_Xob=PX%+A0ZDho+KfrtlF z{fNQL)Y%S$(!o%F9HD(4+F02cTQ+Px-S9nhWGTxmuV^`2gdXbu)cI~QRa$K%&KYxq z*j&2k3yMZRmg)w+vQiZN;01UJPZC<6_zg>&5Y|mU2SztViv`0%+Ka>GffJvO@DiBl2wd8f5q<8e zwUuc=NH~-touN%q1QSm7;M^pd0()H7>CJ|F=}WR=Z7cA^B$K*|Z37dUSzVF<-mZVG zb?OSJ|NlhViNZn)Hov}m+ZtO%)&wrPE}0<~ll8xzfCRnF7$saduIZp>hSa6fErdCd zOUbE(bw@8ZsMk%kDameiw6@uIorXY3F!xqinXG!*`i8I)*SsI7>9o&kh;M1wO1LT3 zH^8vo@<=jzVP(jq>(ullYtuE}O>Sp2-w1l87h*^E&%-!S2_oyhPjvwDO35BR22TGN zyAbto6a`U|=b<02|7lVo?f4wPiLHW=$rg5e>{yf%I$5oMeW=cP=<4GrZ7plYlxKW6 z+3vgwhG4|~r81p!?r=MiE*I;>K|4)s7?*Cd_ND84eD|-B1i(4K(+r4<3AfiJy>olN zvh!K5fD?GKMl?`GWGzEG0j&ZH|Z-doWL=?b#A<1kISRk zxqk~SXp)fHRR@qsEopz#i+}+N=^7rfE+*|52N;XV!$f|U=o~!&LM*dC<`d)BRLBfY|x1;UH4B+#}8i~HE!t9xH!(a8c zWf8%V6Tf{R6NYP2%EVMe>u*ZCu;w}D`}H|rm-M3o{-1P zePxHthk|K3rc3pG;9+_*60QA0ok0DeGaiBj01Zn~6@RA&uMWWw$#nC9v z_WIB%s8|9Qmi9o~E|vDVo^Nc9Yz%|<>&n2Bv%_1mC*0Urs10BRqp=Nw6!@2zV#U+& zfYaAgFZGVt;x6hd)-@;Gr=T};Jh<^S9dCO*wb1^Ve~@%j0M^QKN&lk20={-XT!!*^ z#nZ^BHLVUDsIQS}1a*(YQU;EAA!RHdhZ0?3`VH}uPX!!5jHtDt=&N02I494o7zt+H z0o$r~|1NhOP9r7^N0tEQNeV&efUE|39#XU%}1GbW;~AHo(9$AF50yMAcCZFUvC z6~IKy$1Bf&S;dB0hX2*~v*J(M4Ggon?Q#(=Vq?-nYHtxXMMgh+3`4u)fox(Gt+SI` zr0|+QL1xmZ+HFOwtlc~ISByn}+E{;!qjb~W`@*X_2oJ482ZfhDAiPJ?3PF#L!RVM3H#B;)VR#qI>YOwL%5aeS}Bmn23`QO>Pujy6uvasJLy(>6QAtC`7Ol0NfHH( zR16n2mROr*C9#5qLkZ`2e2hKhUfB|I@NSr+`gI_qMcg%!!zCQK)o3kif~!OEC9ZD| zAvKR$fHmx-BV5M7+k~1Fw2Jd~$M!TlKa8HHJFz}-YuaKMw#Ec#Q3MDeYqVXm+3KS@ zvm`pDx1&(f-@((_Wk)c^@9&}uB7Qqc#}}C{c?$naNSObNua~uB^--xI{(g5&o$3dr zlzo7Ofh$kK_sP8>J`*%U=Yvm*a7lc>)A5vTa2A8x{}2Miq+k0>z(2gMSTv+-R$PTuWR7IzDyy;!ChZZ7+M&1Nf;BYuOezm@kk5JZNP$+a2DDj@M;ozv zv;rzFzZA{NaB3G;!UKf|6}91G2*keKJ{a`MP@+A(4aOiFbJb}6KHBn~5U#)WsgPJp zw%KbEW#C?0`G5#;?KbXKA8c|9C6J#dddb(ID#b=_50${d9vsttSP;?btP%nuLnTJv zGXPoi<_dNo(-V$$Dz8jxbCLO;_QbzoXVX+~1J5dDu9F5xLrCuJ3$DRE?}|3i0}lk- z;_(?%7V?3q*q~7TJ=}5nAsAlkkwl2zaJgr3F@qc*$f}@BssPDI|Px(psd5XfHInV z;@>}^n3#`l{cQ-u(k!Rqu&oA!>xTfSG20h1e!_8tUGu+`qb){&$s3%3vLbc*FPQb%c+lA2IS-TtF8O z_KQ>U;=^-k78$qJ?7B0jgo}VVgTX}YuGjEkbzn6}%yvtgu0k4$LBqgO`~OdOgaM6? zIx)Y?I-~{@hy1{yZ7L4f=0I{ZOSgxrCXpEP-iS%k*>{TB61(40Xr33&V3ez&Od@Z1 zdyW7zqvWQjtT1aliCskZn?e~taey#6ZQn?1cW2v>$u|LQBfLkL<_{|DpizyC8FxPT zoY0a5!=B8tZ%m`Z=S?96q4SrAW|hYVv=at^)2~qCO6L>Z$dpc?vAXuGH0b>D#&42N zru+W~jC9kx8kGGHJptRmiwOF%C7psYwe@)gA=@B|3kJOTgzqmY5SInd3OB>p3tUFQ zIG4ar6FOybGv|P4!EC%?r@F8MT)U38S8ih+j+M}{Gg6`9e%*YnucQYPnWheivi_-` z?XjiQypWhIkD17WW+zbDK*NtWF-ap79~Kf(o{C zKIi4H8(Mqv_Fl#~UyS(Ge(e>UlP{(AQw?VFX|5BkW(;#HwJzVZJC=&NwJe<{xLLuH zF~+}IEF}=Us$KBzB`bYa z3K1Xm@f&4q-^;w!;+@Vx`n^#1ttE|Xys(M20RAFeaRrm8eAeG92nY@`Skh4kJ*rps z%!$%fcl#Vu)|REPAIci6IKYFg6azrGCzHd&Xd&!T(`)Y1+TUQ>ik4owoCbO1A-`gc z*5BB(rcaky-018*LCDmqBWL}s+2-Ptf#QlKdq&rYRJw=`-I4fmmy{_ceTHdzPa?y4 zUT|WR^ulu#o5PlQE!|02p6`yH0AEEfY`e=E&Wh4fcm5sVI2Ze)YYlfCc7`&{TZqOB z$^mY074hVE@?ls-tGom%>Qzwa;Nm*)>8k9KKW?FH3 z?=hpcsxn=>;QXIzq!{^UtmSqup`Yi-fQ?m0=~VA^?kKXiWEbfD{4p}xnD+8z-=rwS zxw!k^o}VH1%!_*K4M%XE12n78dYBq8aN&JhzCw6%ndw!TJ#onrp4~mKBH$GnfOgn+^vY zzt{{)Mu(lHwDIKn!+i>#ko77J>FDyznqj51MPqzt($cr@?t8e64EmP6NU}L&f!(1A z{Wh0O8+uW1X8+U>8xWTpRbfEMgjFn(5TjOLt&AHXmWO61n$-VQ+XQDY=?nkyf)hd5 z8)<&ujGj5>uo5>yJ%Sr*oOBQyD!*VSV*WKO2S9uOy8Et2hN5L11~E0cCW10Qoz^~2 zoBx)yt;=&01zV;-37r^^uN?^jimkM9z;X@dqN~g#9~jd}$|w=g17@a$MOPfU5~u}S z!8GLZhnx*%1SD-;zlqKCuU^;M+@rgGrK2M(^Nm$H2khnYTdV_OQ zWVPN7+{aCW;Vp8UE_C1ZcM#vxN1vs(OiTlA1tuob8_GE54PqD)Jk)FDIH$o3-v!4D zNP*jYQJ}$njpipm%&Y71I5SEU*6O3Y)&<_2R;knn%qw`P}V^m6@p#JcGGpiUG2|%+aD6-ElWrFLMTT19MuSIGw zCh0Xn2(4P}KUHG=2o5yzmK5n|%WhgkYDQI&slYT_^Up*@tk;KMsu%9AY69>@)b|(0 z$qRm+z&soom*^y%e8HlOy~iFUQ742YLyL2m7SO^AqqH@-Ibau&PJsk5Kn9BEu!auk z$I{0gh2b2ltzB~vXLMIue``W&p`$T@G_r2Jrpo4kj+YiV%_WQ0su49}s~5SdK+SSq z;pkY5&BJC1raR7r&f)6}-l@ks`hyHdSXK=PpQ8cB_B;58iYcmC5`{M=qwWMKR6&`> zo`e#YlqJTXWJJJiWZ(aWzb*aGPX3i*bnf>@?&@<`_uxM z5A}0NJxS0+>`Tk$GoQ{N++n$8xXn}@piAI^$0?_8=#8Y?P1&>W7lf#J@ zz>%W6Gm2>S*R5(#aY?gkfnw5FS|BA?ri2{foDO7TB7CV-Wr~FHRpnp%+r?XRoblu7 zNM_G$ov$v6*5)J`U0B{RU3RwdMuY26(3FEW-2?mY5W`Mm*RWsT-b_-MuZEp^mU3PK zsAh0M8nKO>k*7ICUi~|B$H|{`NfgZhcP-A~yWILK_N?W$Un5l%gOi!U#I3D8;%1WP zZ-f{~R2x4g>E!z&ehc9iS)ySt3|^#zaS*ptEHYc^*Ojhutou&m8xoJK@0Yv`kwuPz z>yD8z#FKYL+(nHwR@Y;P<7;4uZUyrb0uvKKW+f7WT6W$#3t=ZA#cM2<2L za>P&j35y%~CT>ITT^3HV(p1S*kz%hfuCijM6UCc~@sWE>GzRt!`U~|cRLBeG`QwMa z6S~Uw_ki*Gm8nS*r> z50!i!(NjohZw78A*}TarEtDy?Ob374&kO350woCms1!dvVzoD{wmqSC72T%?GhpmK zqc*_<-|5WxkU ztQRYkmtKsV_ti((l$%wewSRs=DIle&><}$@deU38+ClK=sy|Js``;QSahyvF9se2s zG}+BgN(sV#gdnl7Dn8Cbb0y2W(X}8aRcB~C=5Y*OG;3mhqscY@?4fD2ZFCoDrM53#>`{}^|rHgvI^U7ch`I`i*uZMs@Z@8;lN zL5FASnk=rXOn(|*6oz$4@%+B>6@M6M$vFnby9bUky=&9`8rObltqkq5VRgK_3Y5U< zMb;omDbo^^GY!hwE|hn850r8FgP-{)Dp#ydl95-R3*bwDa0J8ayT}Z>wpuL%x&9P% z>j*QZU6;12$^Zx_sWDME*!f=mrbyjhFX!#58htuQw)E5@whC-eMaK04%xd_SxVZAF zKM$+&N5n$Z!?1+_z0O5wV`{@8@R;GUOT+Yim;R(CSdV-t5yyRre& z2!1}rIB9{zbXle>%lp~Wxfi->U01?n*95hTHvr@B{mSU=veRvB8t&EqJ_p6xcZR>6*?M*&8##tTnx=wQ!C2F-9bUv7omC)E@cqa@Ne5WB+8@XcK{Nx;EmGXQk zP3+u2(v=QrCb09vI1ar{`9YcBilsnYijQ%?2|D-qnwZEttP40G;|oeX%fSfw@Apqt ziz07)sWXk;5w;;)E+Cpefu};+*z@hXte5{Ep4EX%lZCwNybp;QOjPCpt-F($ozW)3 zxA_Ilco~&zKtNaOt+lT(bseb|=ZsubBW2Wmd;!74){b>YiO7skpoTHW2N(^(3Dnbk zvc{*-v;?QRE;?e8OdCjdf9{WL^%2FG&$Z4*?Qt`?U)-tHMPGz2sn^$|zOiRX{1rEg z{}dv(c3xQoef}bHgU^VXI;Gv|848oL>@2H-wLTJ`<0O z?-U@OwK2MBUCTegEg3SIyktY*4&LY-Ug^)IjBZ0(L^|Pv0=I1~FS8?8;ZRCx9*P&9 zZ5JE-iHJer-j>1w1(V-Q&h`e+J?kOVlE?(&W;TK+Po?8*Pb|gi4WW=VeROrLR%hI+ zP|recbpvdW@XeJVU!4JmYrFKu-{^1{E3@%J01{8%iAGDB;_Dv;i%~U^927va=Lsnd zqp`_@M;HkHX6?;0c?E|x2+9^}sD)eKsg@tfFx2)872n*g#2k)N<;i_aze(LaGYvol zv2kub!P}QLFK?Hx>%KBc*Xk&*{RghBy5MlFXSxHjlQd#wjGlQpVcjl)=ZQhs`}J9K zskBXnK@|ik#goffTVM~bzB5S&6v&PDx6V%jaBkY#}lEG?K2@7U8pjp zc7*3}NKCQW<37CD+0?2(_SepiGID0)Ti?12*Ny7vGOfj+B)nxqvjBDCY2C{b6ST+-Wdg}z0O&AMiW0m zs|!VYa(UZJ4QD4b9vkIBlgTm>@s!agyc(}HF zR3AC|-rtzPaL^H})tE8Vv+ti7T*LtpK^^1*30#{}50kaxPXYar*KbKUT}8m z#Gn>CW%g2^==Lc@``hFh7YYc7lrmbjm-6L*dgSa&SBF;S>;PB2Qc64SW<|YFY{K%3 z1luu+hctzjxC|0SEG=6;pcBS1*LFPhed;loy|`6kih-q$yL@~$MGVr9F+F^SmJ`A{ zweNFcG*fz{%iX$=38>-ku&gH}nRj;v6V4fEl1$ zw`k9${G7B=hAAEdfaE5+Bw1J&P>Cz=rKx#|Z+28GMa&4<7V4GGk*D5s$eA>oV%X8W za1*N=aJc168;&F?d}?OYe(%0Q*8w8L#Xvjg5QqdPW#q+Bj@MjIeOdp&@D8eQH{;Mc z3fV{?{SwhCo_A5ZPHLeHUZzXiqykedZRj~zyw&bEmEx`}wq+um4g`qA`U#}gH34l> z$*y=Ia)Y9XjPSRVAPmmaA;8UHG^#&QWZJ1c+azTB;xGE7xbvIA>ac96b7s)u=Uclq z)UFv*l1;ngLAK#_PLa&2@4t5N>KU;RXz=$@T{PpBzYHkV`GY-)^@vHkt5&zst>Y3Hx?&>Ge##lwJ#xa@1yHYj zWw;5HN!O(MZmsa-3<9kNmUO(B(zKTsCC%^v5{QiDGP!3H@Vkq-^Ghwx2__7WFd4#V z3KBEIOPamYc_U+&7AnFGgl%DB(R%h>R?Pe-oPv;=em%O%@*t?g*B3m?x#O;A9SRlT;)Kv|~xDQN?+I4^MLZnCsz&lpB<_$({t5-(Jj{45DR61#BpkSuY^_WG5_~-S z6%jU!V^k`{EFUr?C4hZv1d=JP8Q>Yow*^XP@tltS$vZtN_4B4T3Q$EI@3Hq1=}KU} z)-7CO3x5SNTRq&yM~FZ_oNY>Qag6cX3*{*Rew%I-m^OS;>E>IeChfLW1k1sl<0Ub3 zoftO)N2C#roTyL5s75N>>;n1YZ7xs;ZMbcv)n9E6Qonu z6ckRoM}w#nsSRQ7(|;}ldNd(oXl+&_LYXi1U&17)c9E}P@*F#XaHeRxK#z|Gz5 zK^c>#`qVvSs zYRx-S_tj-xEuSHPqaK4ZG93^5SdBnuK%q)6l#2(u8rXi*h2Ig2kl!ht_M;T?&rXSRWh?pinn;Kzx~H z#b)GNQ1p>USvP4iam2?W4l{Ws5|O_vBjEx6;gX|ze5rv7Yxbvh3QgmT=lDGvG})0RU=ooS>k)IoB=^zOWa+n0^4FBl}Di3J9xxb}a7w z%8QCw9$~2D?=vdDILlV8sGyHQ-BfH%hngN27iW#{e@$D2`Halhj9e;Fz?*d;81H!uSm(cKOzNL4IS&I~!G&X_Z z&R92Iti!RYafVeN1=$zP-d0nS|4@=7*=+#%YaKPXoLJlUeOQizcksoyri{_xLdHp7 zI$9zTNejg=4G?Gwu$Xynn>9n;bSEW1C~7|~7x2eP*>1uL@5ja06a|619<$nzcs zJeMXQ0&8bkLza1p$jh2`49_h7e7Z=^^^(U6>rZ9bJS1K(=tCYDXH!{?))Oz!+XQkG z-n7vpqL$fu&Lmg!sMNMz8gL!BykrFrAwM2a#ntQqt$Up{>bMbmtKkEzyv`hOfx`oQeb1&Z(Q#0-F4(P}h# z@OGv#Yy>8~kcz~MX}-|BZJ`HUxm@?C1IW&+=!VJBT)>X2eUBIZPCUhf05L$$zaHk0 zz)WF9KNZXoLGQ7bW;)W~TdZrNQ|78ySLId$H!^9pQndejgb24@duILA9xeG>?+EE| zErccLi4qdXNocQ$v~J)i#8j~ZRUKHS>{jgFujVaIzD&1GMAJ!G@}dayq~m?fB8n|C zJgL8r7KwikM1;Jdpe(b6E}1rb?ma#pz;r%tV(_Df-25k@A-6~dMPe@3Y)8SiKEgo} z3+XJ(DpLa5$SNga9jNf;os5MvNDr4atyr%$h(eQECCAK>P}`V7IA2dTXOu9&h>+;i zFj+wn1|7v#hC=d6U>%_dG#plI<)eiup&G6w0m|r)T80B8+gm)TiV*KE7$27Mk z8s8rhCNz;ynF!6om|vk8Z==DVDd|hDZmejIy{lI-zkQ#kE91&d0MJ}Eox4yJiYDKO zzyKMrh>TV$0oQ`n7)UmYqYJU->%H$V(vMhl{;Wu5%G%GW6}ad7s6S@XejZ;#2OWmj zJ)yxIys3}vgtr-p(~9Q?ynMXbDU6o#R5VCnx1Wi0WBaW|t=TVc-ittT|>loPA{Fs+z z`<heS^jW7N_R=*a*ZFFW{{=V6NylI1lSQW$6Tw zJbq7~*@4L0ets$$Sr@bMRMJGDp4=>WJ42a(6Ext*uA`OC)6|kj@5wg@IZ8SZ;?cF? zN6n4oIgqS#;uycyiqWDuz?s<0sZiGMAiUVd#>k^b!g=4LSUU7rB|`KM8o*T6+@s6( z4gv*ku_bc`dCuhi8qqJ+#Kl=nID8z#^D(3vY2^C6_>nKqd-!lz;KyHwOo9oJIMfKy zWQpo4lpiNvg)B#I%F|o zBAP43EhxZfHI>*}>y^y^fosz3=)$q`|sRa zv6Y8LnDhw9>Z$9I0pZg2^D?vie^DJL3(FaifuxN0oC9ldfEQO&&t(zGfM^_2O%TI2 z)g}J}Nbg z6kk?b<<>os(BVp&*?*xiS`WAgyy!N>e=xDe=EId$Sp&ePX1#`pO!sXZBPJwj7>dPhKM=oDOpwSp&KC|B;ila#Q)u_QdTI%5j=G_X++EgX6gRps?;o z6^%BSqM4Fm85Zc36{~7~7NX9Y`=X6x@a+K3D2qY+JO+h$vwDED{yaRAjsGNx&QWKlW)}}-B)FvNlA_5qKf-^ebQY5ehP`=#9i@U#~H8O>f*}W=e(P;x*%3sD-+Vz9$Egw_!I>`AiFLyOjsc?5W_K=ia?EOE| z*{XQ9bx-{J^fJU;i^{aMMtK-F! zk*5TPu~3Ev%~(Wyk+yWDU$L)>4}>?y)sVk97AScF|82P`j679(&qmoYhok>Y@B4g42d$hWcPZ~UFCHu@rt5=drp#nono zjzGNPy(2}RhfS{lJm?lcbXHj-=rp1KeUFusa)2|YrE3SSPkH0N8ai*~@>=SMq3D=r zk$JBEf>i0h{`|@9ja1T;nmmD0piS_uhNg3lLoKtSp*0vKb&Bqg6xZ6mg<;YM??EWo zG;^)RF1(wyS`3fweY2wh=IewBefy9hL=SW<>79fde%DNV?g1j#B1HxIypW~O$d!`4U~gZ<8k41Lozq^h&a`Bd;_95;Y|O}2{hm7 z&L^wpBFA&8!FtOS$16G5pH}t2yzEOtO-ej|Hmc#4&11<#CZ7h8gzl>C$8K-SS2v>>xPa_JiNC3qn`H8 zZv%2JvjVOGE*v${@o}Hl^0e)W&ERy~tgxcNHG%Do{<9qhG$@KHd!41*50SS*xrGwJ z(~B~-0f7B==`!`#d(!7o)r)wt>2THcq&nsAQ>j+uY4WfO+-clXOZcu%Wyy2Vp!E1i zfYbCHs_{{5WA04f>>fSTR|rq(Coq43#Y&8*5$vL>3xV*qHs%fbo>Vdb^=0PNlsZyP z&#u9Lz8Y{;`0EVQe-4{9B%tqEXa5|xvqYiDW_J&aGr(%NQ}jg-sNsX9j?p`0(lRe) zZ=+R~um zmb7yAf(-1gx{03hM= zB2#RPb7g&{kZPGKx-c^H_;Htefz*wgUpa*?JJ}q{2Y|Ap(ujZv$$xG466(=X{%qe# zjsSQ3d&d6>aL{;!$v_p-Y^uwgaAa%t3(RKw|*S4{Nw5W%JY) z)xGm8{Y|iu(m?OJJ+ED13YkX=;!W2bC@ z^)ROwismomxD{lnQ<{wt8y0Sg009MJ!%5%Zc39;<=auUOgj$ za>Ck2{{`02Xza8AW8#g`D^}m%1XMD5D;%f_Nv7ym)ztS8+VsYDJfS^W>oEp?Wu6|n%Ti=o%pZcNaUO^*mnDib zs)qV(42|QQh~%c4s|fgQjSUmmv>D$^2(sIPQiK#H)TozU2>t?`0FO~_>}Y2wS2`0F zL>%v+K3u1M#`DoK3X3^vlM=fon_MxEd0TIa_lgj{5eIs@KB#w`j=)s)x*N*a5URWx zlTo!)?M0sqJ+MioQSz?Q8G!dYk34?ih9@IdVxIfXFM9kBKhdUV|IZMiLh#2a%DT0Q z{=yfq>4NU|GviJ@Y|>Jvr-c#iBsvQ#rd*VhU}vc zzngI_(?3k(qwXnbvWpH_`>#>rq`eoNc)?sSQqC{}s~RbxOp z7H;I;Zi7?mU?Z6_lN2R~gunLpPKTPQE1~)wa}~w2(3lD`FQk~#ddu6`_OKHNMb}9~ z&pX^5{~6;zVGoDpz1ECHoReJCX2syYf$v_p9nny7tIVv#uvQ+g|9MODpoE7*$AIq< zLn=J@(gOQZi!#~oycxT|>5&cd7&?5efELYXkqqzL zYhoU?#m701u)y?%{1ZGZ5V4=GkMM$syCZ}o>OQs6>^cn*Y**+87hTNmvH_>UV@n38O$G@(T}DTI#EYHNxG>9@-P#L}ZK9op|o9ibDB3W?~Ub;eTs zwZ4IqlE3K=pWT6?vE^6Fq!`)C=@A9=3r4NLgtJ>2T6Y662KQJiB|D8li8CN;8!gu^ z!A`Dte3PIbtn8Tamq#unw=!_Ylw=R}N4*KaHvLq+kBYmfXLl4XKB%=3raRes{1tUb zRIG?)XjC5%giDp3@F+)NMIz8~5jW7z!w)%cBVmJcm^07sz-jb_SfV^*zcdO&>cg|q z4e0&75}6Pb@CVGA-)!Nm}^=MW>3G-2fslQ755(XC*Dez*mO!D z-DZVf1qefqrZ`ryEB!^t-gLCzLlSqPtxoFGb85`YCKk>^_(l5#EHmhr0JIu}adNRY#jjuApr{<7hXFa}lOAAccpr?!`xe znxVK!qJE*KgG5%(c!(@)g^>AHv`e$p0iE{BjPM+M)}7NG}DWBpw0pSitR!G-P@tt~A!!i%+x(GOgBkP)iHgM~%6 z!ngk2p{kazYUcv$A%b%yC&f@cw9TNrtt|5zQ`xm4!u5%j(C4fS9UN*P-#PNIC?GV4 zbuWbnZR(@D%%(fH6D%9-ATy|Ex*jk#3kYap z7!QLfeab_y3D;+!BDdX7+GK*lIx}M>;0v-4k{wHjxW+RT4A_kDYry8_u4#cxcHVIg zocjm~kTDT6BD|<6STq#1hM37T>XWlNCS{ZoR5HlVEO8dAxpWzk%Xb9WbM(n6rG%{R z>7DfKU9fb(*q_OkP(2+eVRDPlG^;T`tj}3ALd8HSm(T)|7Jf+>>Y>K*8hzS1ION_f z=)E-RL-w#Nx^zrUw6&|pWV6AbV)+n^|jr;a> z%4V#CYunBddg+CAcoaujDPHBI7>6f~~T%Q9^)(&_B#Q0jpi&cg1* ztfkF&qOn1o`;2h0{xg-ywDY`G*?%*LfIjr5U0;D!{qou_k=qnG&-Sd>*HQ+8&#lu4 zE4EW<>-UEMVYQH;f0%LzqWhrDH;iyYi}~3a7X}AWBMk*E&pDOw+>W0jj{*k8{+U); z6iXdyMW2fC@lUQ{Qrm0VrZ#%V{q$8GsxT5LJM7Tzr5B8@t9WQ!rv2$kiV$JgojHN4 zquObt9bLk0Vu7Sni`Nn)<1y*d&V4@mBg+U_GDME`Hv2^X{Wor)Nmq5uCocZ9Zsc?t z6Z{q#jRYc}{z{bU=a(EIZ@}dpGlGMh^*M&6QUj`)UeI%s0C##49rz9nyn@{}#7iXB znTGK(dP7d10=W^8&8|LMw3xWukcBU`%$``qgsMI}BNfWuwVvdu)Mp zY#chMrh3S9>A2YCrRiN{9J`nSD{+>H@t8f31?(c$7hcN59}p{R`C|M|x+=e22=e zws?9614gZgES@LLCH$3m!7gx28>jg57jMVuFq+I4dCRIOYW3$1rN7`|` zj?;!Jj>mA_-7X%e@_6F)lCR2Ev4$q5c}yRl*$R#k3d9zWU=bS1LHxW8Fr>|>5T>H@ zV6=6Rr$`Ui@MbrWhU0z5KCw-X$_vOFKG8?PiqnZws%h0O@R_cp#h6Klv5SXE2~cpM zT6T6(6gf&G>{dzUpFU4;H^8`~75EfdtU;5o6g9gq%B+~x01{_)b%=s-j81SQ=1zR4rdoF3&I(aPf3bRna((tUO)aq5n{x!*W|w!lcS#y%qO9}e0`EspwC(*% zrn$YI3W1tV;}VikQS4$q)t zz51n*kLUPU^!k79y)#^W?WgmU`mqt8X_XO7C$#r-JIZv(N;oE2EFCL1%64LTa@K+U zt53Pj=nZJsG!rCW9CF*&$wlNxY{#>eYqta0(ah0YRk;O-#^ZI(0ZKpyEvk|d3+P&B zpyRpu6|FKc1WG|%6*&gCPi8-z|AB~a5)GffxVo)g+2JrbaXe>$T%wd+jsmveF~XYh z6w@J>ce9&}?J2GfkrF}24*wN19+nC0G>+vsqEcs3eD;kbh1ao9Uawyo*-BYn%wk>JxVw|zG&HqvG@dc-_z7>$ zL&4uvjJU8@K)mu-A=|xSxXWR_N}OtUNlglcdWw{9 zSt!~A{TA%ztG=hhsrEGzRqmlZ7*|eYIh|B8?m4tIsv2S1Gu_UVwJ@u^eY!TkRZWzl z(-|6IexVRT_{0-szao^>McaYCD75X^TsB1bN=?Stxpm zO)ZF$&i|*}=;rr>Q_UZjGg}}QQuD}=03X9~+PZN$%4-on7c5~mvvXB`>f9g(zwxMP z*XI2nZr?9J=5M9w)Jrw$Ru4ig9iCigOA5ABUHAUZVHy7Y5nZ7`kX1f3f^(90GFxNf ztAbXlzBmOG($3*&qHBYG(lB6+`A~98ZL?u#z=E$2Pr{g7+^w!1qPDEL)Y-&^*DOJ5 z)J7~Vj*s{o7#sh!A;4DdDAUAl4izSTZCTmj!*98ewmC94JN&9Q%g)H8-Y1=>g3Lz; zksfmmtwmw&8M&fhkB|)I4SL?KY(q)nf;zqeT-K9?8bO09-NT(f73QlwH zDxS~*&9lZAHI~43Xm?(vKZWp3k~*m(bWaz(V^}Ao8~5$K=U$JGTzF0lUYOJNa`RMK zgwVy02{>~&L@cLY7|fjrt@M@R7GS7Hp6Aluqxnk~R{Mh$CN#c%AOE1&07G^>qF%>& zpx!%DXjje7xlXp^u+yf^jS$&B=2j3Clt%24FgsvQO*L5y#J>}4Q2ZRg!KgDsQldE1 z-q?=dNt`zuS(&B=TJ%*Ep9PQUiz&;9S_wU4Kmrg`2}2!_$`xe8ZPH`hY^?kAc`6DR zd0bqYwEV9KI<)U)ZPdq;o0NU11@uE6@Qcf^S%KZzGfy_L#V?W^UL-5l-;6|ctFM1X zLnw><`pBu8Q%b@xxX_?6WmZX}hs;fpj@g$!Hx;YNOw&m}bAp*Ez6t)cgto==6fH_x;ZKXB+_{ZCfNEWju)Ix& z(v{W0CoPuQZUx)Mn$FZ`Qbm>AEf5q4+-jl_wPglfEia+`a)_nr#Qr`A^(owz)=*yY9JmvR! zWv5$o26NkT6uc0@BX`M{ZB;aDL@Jh&k*@wvU1$%?r`T=2{k}>!qieD~uz6HsoKMZM zt19His<&tpxR?!a98E%m?V^mugElO?r|iQ`lFT@0?og9?Fg8BkJMq$0%cm2c3Mr;?{x4^;63S-BLFS2@EEcA|IZTR zE-t#sJ!YpN8h8YR@^EAEW(FGp0V+D=}uK z%|8cYb})P8@%z-?iW9o?FRNVepQT+`(0aETi?Cxbf6(^`@W#}L?h-C5&R|;(9_82S5lS$8H60M$~8(B)0bUuY~rljc5iQI*CE!31$7$~ggphr(_9X#>=C3i zx*SfjoO$pz41+{6MzmMTjGtz&h7kZour&+XSN)9bw);Y$^@TnLHij)Se)C zRr;Nvc^nfk$m>_w1p*vWip-TXjSQlplmaJlDloxDyxVX$NfN~m;?wc zdhNKRX<;Y0Jrp~tIvKvoAL%khL$k2~ds6>*uJq*#sKoL;_?1$QVD zai(Tkbi~6mM4`%4=dw~DRD(JZE`5m@%{h^Je6=yy@Rp(?=BKDH5ERXKS<+hRtpahoSvykrEPZ`Fk*czMmh>7j zRxUVWHSX_}Y2DcWb5H18YPa!p!h|$ogS(FFcXHatQW;*)%l->+`PN&}G6iy@r0)yi z-9rhXJ#1-cG4M_x)>lA@Y)h#f1s0NO&Pb$LJ00tVm&<2k^i!rlfS1z~o}-xkN#^0m ziu%6oQD(*TNckQn=HW*~u@Qh$tumVN-rrOr6EUo=`MgNd@k`I%LOc!FTF**>Q4#7&43HEXkZ6el0^b;LWD+Ss*4+@*5W8>J z#cM9pyYwgJUf`19=Uq&ve`;BM!AUmdU!mjqz|CWB^$@2cqOf1p#eg9u6q^trsLQ2^ zHcbo_Qy;HE@#9sA)catZ8`9Kh+2{u5fTlcNnhFexK$RY21RC{%^Nj|C97J)TpvPeY^B z&`X>(GxRx(qOK&s@>7zPvrMLaT$5i5w&Ov@BF*}Sph=2jGCQUgat5DeCa;xn?fk8d z`&A*GEg+$eCcfmFefnOy7P%W#8>&+sB~-I`pF`f)tinXf+(C890ezt(IR2JIC}Rq1 z<8ifBw`zMob(Y!Yt3d!y5qYPgykw>X82#!A68OgY=)1NM()} zbbf9M_u81{5tym3yaL43Lc=E(*xVK$SeCgOwbMb?Gn(Xv96HcAsDVi}KsvSfCuOvr zB=DdJ8Zl$0Ytw5iz=Dj2V`EX@W?i98bcOIy)(zIbH6@itBB)9WzWd!1f8l2*ay>Y+ zuvI`3LC~)+79&|lI&^;DMpL$svdBS>Naeui4&M4@{?8znM^61`ng_ZO%#o`Z%CQls z*`3=c9)LQvLbpl|L)Z-)sWV8JSppLJj z#!9-kbb1MR?C_o$1I#&!S-k^Q0{G(1QFZ8K5O$eXtfKY7pVkMl7Tl$nSUKj<10eY;Bl|BJ+ zP9XQwO7mc8E$}snQB2CKc>SzRHx+!q)D6$2xE-&(P*JRA-Ca5W4M&YXODKlKyRs5@ zy_#Z$XNMy-S{4mv>P&P~K`wC=GE|PzDid$;1FfTQAlRWAR)N@401i<8?|WI#4clOR zpTHx#o?r1s*J@*cif2~OKBRD4I zw}ZA*^3ZeQ+9m@?oPf?E?%VFw&(*BdeTCRatB7blHOweJ0QhK%C4_$@RbuXjn*F0| z&q2isT6oj?)7SRh!q0%U*WHvSu5K&-2RzUAo0PugOXlG)-$+Oo%k#KQqJq;~&CiS1 z;Gk_I!b->`@pKv(Bt)gl$l4MCp~IlLD+?sp-H6ikx_YQ>&@1n;Z&*1}IgL`h(0MCY z%}{tQ+L>(@Gj6PyU;VhIo`O5Cv&%$P3NuDAx`x^BhZ%Q815>WJdKAVyi5>bDaVYgO zI0LUCMo)x#!j|-U2(nOrZfI09MnS0M8>x3EdIzyJc%p1SgwW_HRY29%U12VeoFs~e zG?AHebkZf-7&>qpjTeY|oeX&GqfLdB*auyzOyd=_@tCPHr(Gh}VaxOOf*g8_LZFrN z%NbiR+9Qnf-q$ZAF8!csO1r8I{g?SoMHm>QGkdu|>E8eF^b%TF6MGAo-qnxfR(A3( zbEw=ek%t+gRDop(8SmPo%{OXo%Nybcl8}Jq@$%^^&Po!z461$*Md+8*8LbZ?qchaF zClPep)2EY`+x1TSsnZThCH~dkUpGx(4ATguF&pPp1j9ZpYnY^=-*xF0b7FHU_7G=y z{QN*-y!XmvzVFYsYj1m8g8t`dKBcaNuZM_Oy9+WXPwkKjx-fn6U84C+-jT3 z6KH=`$uvZlg{n1OPYe;^Al{S7b3SKYuBl~W>t!pMIbEEzl!=PfZWXo|`Y&q%uPj+e z%H(|)A*uf19)&l-@9>N1?4hQSM@szpkmF@=MqDqiXxL{{1NVezxI~YdLiM8w5g`Nmbfg~Fj9;<>@~XR3GVXC4d4jDnhMt-#)kj}FHlAhoK{NieI+m^J{p_>!<+ z9ASQQ17U`lKe`hay7pUaS!JYHvKpC5$l}|K#Hl}K&kSn>ADICvb~DV!a*wjmPpCJL z{hOirSt5DmJ8&5iy@xoIrf<>1VRBTa>HNwqZork)$?6yUJPY(lz}yf8=89lB1o5Ca zVE{dYaP4TSRh~gsZ;@ZHrP0H!h{QT$*+hYEG8L2V(=*lUgy@+@YMa+){vp=>;v2X+H==GKrizT$a0KvU5{dBV1@?Ev!jk2Kfc*ln0 z9>XRN=Ownaih3)NZ|nWQXFQaAQOs?-le~?~=QWbxm*OmW;kEcOHf}H$%f&V=H&XRjG?aD>k@FPpcE)&&W3n|4Y5>+({C}8(wd-$!${` zUgtQ9W24qC5GeBROj2Dl(lwZGJQj7IU_@?&sqlW0+EvFdeOD?Sz5NN>n7Bm*tE@zg znHt_Qt+rj>9#p&h0^g?@piy8}!HMd?o?qvjIr3761t$xeIbW4H(&3NMUrVgt*Ki*C z-4tG5Z{L89*b1v%ahAU?1;}y7To_Op_lyfVQFN(3{#~$P6joNshZdKRIwvke4-N8e zO-9Ub1yYU}UTG9^0vNJV3GQjB;^)%`yZ2(CAjEL`CD9}F=CYp*EV8Op*_mP>M4eFf zA}y7+AARN}L^i^H1H~Q7cDkZ}O=GlMR_mI-#bA|}g(%zi+BH|CUv8FALOzw?kwmvt zEf!2aQwj_{&vGhzN_9*n7&0YJT4@U&Cd+Wj3F*WWpNH{~mG>P=XxKQ`$q9htp}>C( zVnpLXVx^VjFzPSj5t6hoUXUceL<~L&`Ng`$+lA;Z0G8~1&Ft0%(oK|@h%h4=tlNuB z@nNm0JvR@H&0MnP+If6jtUTCN0sB>4t%hL&mVlX-g8-W*k1>EUTtREkmx9v+OFEe6 zxq$Ltquut4Hv7=fkYW5tURGvb^*5VqkUhtj|MgL?+X|ymuq?~28r+TAH?`-CjlL%d zy5F5Jav7aAM(FU(MdO35rlmgdCCeVpm;D!D%(IIuu?x9+dKDY#Ab0Rs&vb}#@P{|e zW8aY=N*Z2-JZIOLoq?UYuCzN@FfRrNW9@cb< zSMJrTB|zX0P|9=v4BSX37(V~&B`2dMMylzn};0o z`a&@23vPpOn`*0TAP=VCb63x9(C<1&+XTy{@9NnCrpwG!~QuLC!I}TNj-z02nEm5E`VaS zQE7_w-YjRA1D7Elzy`t-1dVo(m3K}(0@#8+dzi2~=j>@nb!Q*N%zjkmu9#^&{-lJ2 z&0xC8T#}*&VH}+gn3s|mn{UHRia(s{E>&Xz7Cu1^`B*g^mf1K10S_Aqg{6qs#Mn%0 z+wtw#tKO`6GFw72kXHvSGLm%gw5=LxPlJ}?X&Gb52$F=V0UKG}N_(wpy1C^L9k%l7 zhg4i3Nk}S!+Td~^KJ}F9^HEJuzCW?L!JgY1tN`!yvZ!=SqaT=>9u=Y@RJ3%tJI5?H zgr_d0i2gnHO<@zmdgjDZ!nF>w-oYD8trbOQM{9*Nq``ncsQT7Cld?809Q= z$EgZ!SFFrLX^V=6U+M*iHj)Fx!?I-9=(7rr7Wlc0^ALqtqKNG~?I8jJ1!h%4-qo|i zzczQjJ|U1*UI+{%CIx_35S)BdC_M||wrOt8by zp>4$F&{kVsmRh!NVo1bQb8GoyH?fEFeyD*5$ZdqX(w?4d#!asfr0JTJrXuH6X<4+P zSFu7cJ+gcfr;q>SKI}2;Hl~GoEX2c+JQN8`(i*5XfH08x4xvG4HvfhQhL3`=_w3a2 zoD*k~k$7Bp6J<@;HAI?iF&>V_|?zzRZiaoC6|5s>J*gmu+dLHo>Qf$mv9c zNzC_0!5Nm}$;q#ct`{W&im{Lg!2lA$$6%!}E|l!7bBjImqa6UL--OyMnfSKKa(}u& z152v=nLCT&KwRE>a}(tgf-AV2ZI3%pI+lS5r{dXoG4C$fgh7DDaVk61P>tF9<=lf2 zpoh^>7OOG7J*>|vAL~KHp1i|w$;KAqdl55+G%;78>ep6$GUx7D$sb{zPMeCuij##W zg?&#_F&W1MXrg3i1_1vPOMY?3(<45bXtqG&#r;EKf1~OGxj@udGSI1}?bp-UD_VQQ z6@5i@K6Ac+SWQBvjeWCM>U0WWGEWNozU@sPd&5nvL}G|9-m9?N^**@nvio2joZ<)2 z+=5bFcS6z>++iY4-j_O|P?zMV)e6Ney-^6Z^Z1poKp>OYcvIL#PK=b5J-N6W^K(KG zUQ7ZTg2dFoGJ*kJ78@X2=V8S>Wb3q|1+Un0wjsBXS*+ertJmDZW?o)oxAnQ2rWiU8 z#a9;n^`gOwudjy@b5A_p1zB@14}1COL{G70d}b_`LI)8|(6LDrZ43HzshfQ^9DaZt63Q(7XWVZj0w|K?^#Y`en~+r>A@O%)#GRNPF?3tXf!6|DYC zXX~~}uEE7NKojq0y&vVk5A;RO=6fQren}NYe%bFD|ME|qe=*%VT6a5IX{y9r)7q^3 zkN*6#EK`xV?xCjjrlM1eoLvwtU4V_D9huk=FDWJfeqP7YV{g~}BIzF*cJMF!X#4^`5nuD&Ge8=tFF>AS3J|e^U z^=*acp?omxpdUW`A%nUyhX6RU;!)Ogb>*4*j}+fef9o;Bw*R5tq?^>W zWBy6;EHaa=+{-RHDZdOKzDpRNt(mBk^v}+kpgmYG z09jx7u@1!&yH(<&o=W@%|?B_5^3pJafaWiD1WhX)%(q5uehz!eVDKvADhHnxNUE@>rlxs-t}hUiQjK zL2=C;C51E|1z;I}(wdC{OstGr3hUd7DI_l8tcx<^bS*mQ&aqB_q_;5PN@0Su6o8Mm z#Gy{Ubl~4J#;%}>M2V-dR}%-rVNC(0dw;Vn2BqjADV>c%R4jflcmC@>TUFMBm3G4j z=*1Nau|b0gc#4#ct{sR*DQ=^@V9JzvX^d>sfI!gRLh^0(3?cYaXePL=brD8Vs$N%?x~3S$i?b|03(d=acOQ$w?Zq={o@*!!KZFo`^u5n zdW9y-)LJBv$y<-R3O{*`QtAJ#KY*;Z-Mf}x>$RFN{i%sc96Xp#k#ZcD@jI)t#bYqO zux4#)X}l~$>FLvG0Z-W$O@i!YrH}qeBen0-ZHw?H9UYOsh4d8jiAA@i9r>_FHP8b> zM8ybsa?$zf+zCvoYilo_I-(8^;I*YD+OkdT&~kdka?}rVgDImPv*fDP)!*DMB}DKf z-3G~o#~r9_r*#tbMV4PfNKfz_ZTj)-PBG&akdu#;Uo(b?wG-u_I1;T&y@r*tuwE1+ zcOl@*OeW@3SRv~a`fTfFiASW#a*WWh%X|Sr^Z%nfq+D)MUP>D5w4mAzS8F2W#{|rN zcwSw)XQEX$cmT$RKL+U&gCAEfZ~Mnc`DmcJLeLc5d1S<7bh};>Qru=%ooQsCdd1y; z3a2Y{jH*)9csy%PAeB;?B!g_Qh ztFx#|0c(Uyt(%lhB$LMU1#P+5M68HO1;bPD);Z+>)DkAvxJ@nVG-dHfPZAbX0_wLh z5?Hg&*0BDbco$$e?ij2NVIaX|h-^B$u&df@GB}lRYfAuAAfm-Af;>VDdW=8!uXH>u zHPiL*ow%}tJD9GXY}fs{Q~zes6oaV(WIEyF21!J>;p~^DbH#g>mgnVk1oypK>qH`9 z;d@!5x-*P0c(_6n<87N^oDF7?9~RmK*?)4d?AmqzBwawS*w zsYG=?tW*(B&tbsRFkkBw${h2*#IL|f15ezwAEA(b$SncJj6l1t@oBHGxaQK0B41qp z0E>7HPn+6F?J5kLDc(0u9bdnw*wbTQ_riJO<#OPRwg$2X3B--Upg6m#urOyXlr+e6 zGK7%&hY;W^EEuipf<6&Kv?=w5)*MaDaRkF3K=gGEDpr;VU~XqINXC50VjyHJGLb^X zr#fV3CRLNxm3-v6$K>hZKNNZ2Liux8Bj8TS0F{R>ueN)=V`!>BBAHcVz&^w6u2Q=p zvdhD=_a)-2LQ$qZtkLM)mKy6-wa$ZSNnoKN*IK-W;sTYtiw3A9ji5fyCmaS}}^B=ngH9sV56uBqp_x(Be|3nOXre5h=oc5qL&wvWi<~^8Y|JDvl`k z^)TnttRzr9CXSCEVNNCtc=mx_{T5}{*##HB2)7JArv+bQx398_cO(Z6dZ&}XqnQWa>^B7Yh*A$skC+@&}ZA`x+5TlmRlfQQ1 z$tdB_vD08CK5Zt}PF)(!l7C~{G4nqy@FB%Nk~uVtQ*I}zDfr+;Z2-0zbYm4Qp&-JX zVS*)oCMUHy=38~KPhPlN&>1svSj;BnEDJY!hKYMaTiNd|fWfWWVxG@Gvrq{0E}-p0 zn|RaDF^_rl9i;GjlB~e|bcnr`9Gk(Z0vK5lf!TQ;{X2=4s0}x2oOts)+bZ29;)!zk z+dr{_o)t0k!+A?YvU+1ow1q_P@BjVR6wV<0l6HuKSuT)J1?1)S8q~o5z#wu>3y~S? z3OxkMX=1b%QyP{qDd)1q;hnO0sb(6c$Sa{pff%&5x4>}JdIP}zNy)KK-cuJJ zp91RyN1C?j5LdL9bva~3DNKc@LF1UK>xB4D7D3}`=YQL=;3Puh{Zc#axEwJJGyvQs zP~Y$?O&YL9ce9wS#_W#5QC@nGH1$C6BEl#X|89_!@96q(gGkj%FK^k;kEFIaaaiH{ zE_6@9gFb~WN+W5*MT+d8O-_8-Yc>8vAQz%w;hsh$N@`fiFo+Lv**B7pMvBMWEa&N6 zA~WY(oSZ4HupSA4(TEdRT@O#Z7VMJ1sdw$4&H)G3V0)z21wPZ7Ba3p&@?(WXvRd81 zzO%U2R?*_H_M`*BgwPw*N;=d-(Dsc$%fpD-O~^(J(n0Dq&$Q;uE-8r7dn2r(<+s+` z(52L_&ri)@ZdVIKAsh@dM&)_C#<^PAusydRN$^YNBi7Q5cTor*TddkjuN95$ByK9DhVCsj3ZbYr z#{K$`t{Boj5Z&|7`W}5~kU{ug{~@^>qRWgEPh=5=^^O4=!8Qn^Z~JkTt_Ub-fgc23 zY%Y_(E8M@ORq;eCStWe`E{%{lkurbho&y95>@Zrsi>6?)QwW-cdBvw(OMjGLIV85B z^2@Tgv8FQDpqc1!z0Q{_j;@h^;zILqn6f7MKTl?pZ5{6H0xN_m5+|t@Dr$&AndIff zf5=+lfWE=S=NOMC>z~S>;Pf;=iyuDKMj{QURM(2r1-Nc&a*4mpc-}E7m#D!2(WEE2 z?EKfW10+8T&~^u?hSExHo2@`+T54&p`1y4B>Y)286|HDu)pd_;(NixyvTpSk6})P; zg;%nipms+L!z6Pt(BkR<)N>54iJvzimz<-(aYKqNx1;UljlqaibkmLEvz|ZdNvRnm!eRw5!8qa_$%y;LY$HceBi45bxgl&mfNXG6 za%rW!0?@$bdG1(|Oj+a;qq z0c~W08MiBI2sr=+J(Fr9C6pqqmf} zHpjJGHK{{mt4lh{gSPoK>YV&$(_W6F5G6|nvw~slSyO{(dq!P-0DzE~3@OcpxJZoPy+rI7bOmQn6};DV;M+$#bPQh+=UxPkmZWPL61TkIgBmb_g(1ACwQn@}~#_N_k zU^enX+2#?a#^gKo^i9!-!;(a-t%qx1b+4)7NU+QQPPTNcuiEh1CEq+H7_Q5Sek=Yl zP59^~qnLCR6z7fgd5E z75f2r0xMys^jA+-h(*=$0;5tJGEMH7tfB_SK)=O)+GY8He?e%!7{~dqRbLQrqGRr| ze%|xvUP3XRnW%NxVHOe+FXUF0CUA!JjP1`COf?pIgYm5e1~#1(e&*qzfl|e>(8p?W z(0QqY00*0iDcJRdG=|r#e%r*h*Q)9_x2{CB74!!S?$L!cx@945?rw-)AwV!P5H@ zlZi?xLjIv$&i<7#%m@d;G^lkq_^saPE{`^2wl(8JE8uEOR@uz3~Q~^Fl&zoSaf;S{V(oFynXGaZ- zk|Ha&@3u4&8{sCQ?7lN2b(oJ1=xTcN)I|I1P$OEi|HKQ26WeRp(nUe`X!igO-`d;y zYl|pNo{ImkLCnKD>l}uF=6{U^g*ZO7VI)c1;|39EKx6KS) zIsY(0y`kyiz$=)V$?q=-@iFH zB1407p2QhSX$4{3%E~Y2h`E;;<{xXOJa^pmG{k3(#@?;0)=5v2YQsb)Ll^@jD9$Zv zJsCUq`Ya!9__l>5loPC^`2OjreD?TU7k%{rW=2c4F&ZJB5a^tQwDr^Q2#BHeD;1>5 zd3;RT+jcz_`=XuyjAdl6S$Go_q&Zj#KCGNL^}z>hr_3yt>sWv7>)iD7Nw3ndDt*~|#@m{UBvG7=b}sRsWNW|tbRcJ!qE!sf zKb?1|P;*!s zwh2@^#Ll+3m3)`)y?xt?w$U0)v$^ia2XO$U%dqOm zH6~)`7QA1Pp0@6z7;>H4bO;fNEV@Sa!?9we#3eCf2^kQBknAg>A+}dolF2~~+e>H< z@W@97P43fbTwX(L`84~=xXX7nI$y1+6cMwf59-Xzg`548_qX5MIx@`c?M5Hat*gUV zG>vHL}v{dTRfUD+a)xv4u~=+^L#?P^xRNUuPnB9&m9#e=R{$=ZBCVJg(I z4ZHk8baNv39<4rOBJ)nD7t^lew7=Ng_zCH6)TuQ=!ZuFm1oL{DdEO5 zu^}qU{S%p&hCNc5hpRzCh+>edYMn4kf2g`F(p<2AQ~u#XN46w;!g|M4gR3p@bTv{q zV;2;e%1;}RD1sWd53@|f_&ewjuU%$lYXaJ|MLL;$?XVpFttF=q#q z{|dH_xCqkr(%L1Qs3d#=j3+2;BVdNb9;c{*>8IPYn&)8B?i!R?akra2#y}%-A-8F- z3lKM_F`WF;a*e6@PhZ*495O$S7J|ko&Wk@*NqIG0<0|Jpv@JTms_}?&BlG6CcX{OT zvIu}C45hJWfvX+(=oD%BR6=xKHDG$AoI>^pWI$Zg>nv2{y77lw3s;e|e19D@HB8vo zg-pg~oEMH{AxjW_H%B;UmrU9wM-W+|{l3U2x}MRq558 z*hsw!tX$9lRva)g7M*Ecg((V+NaK$#j5~RdcGi;C`{oc==8mg<7~e~I7GlVkuArO=jGl-X@ju%ph zeE=UbL0Mp7=XT5wJKD@Y&_9i$o2RRVs#q@c<5l z>4^0dyYm-trC_IWG%k0f4n7OPEH!^M@mzJnCI|{6g!$4S_54Weu?|i;&UX2V`%CT7 zkxz6Jh(`pma%&ENT6%K0vsAiB^)R5xB`b0#`@doJQc5fy^=B_cQ^*B6t>c%(S;J26 zu?!H;23s_ZmjhU}m&_xx9PgUwL=e=zK|oX#d0#?<(UPY71{s166Q|7^Qoq0QVJy~^WUqe#X(a(!{EdDdiqgC2Rxs_Dq6vc(F*ZIzpw0sJu&yB zk=809NC3ij45X%G1NWkFw9J+wm%7D-;ebnbn9T-3SzQ0Pp+!eoBd)BJ+4GN8L^J8^ z(|k|7t8m@uVBJJ5I1MwJ=X7-wndoputSucvYYGKQlWR7SLPQXYbWNePi_=07I4Ney zwnY}MFFJLi98>~dv1}k9*vE+8PAkXg;}Da?zNCi#k`Yvn+=7Oz2in9I)RDDKXRtlX z)3@4~_MXj!(op|xJTM7RRG1?YxKq<{1CQi4=F-oIt%!+B0{M!bohE_+puPXQo*jO* z#&I8hJcv1XF@*Umt3>i&pBd9@Lo{C@5h$$`{55C-nwIt2m#}GTHR~ zoI30HDPY#)-@J!rq5bpd@NN8jlAf@Q;Uj$|juqK)C@|C4C9mq}g$Z$(?PZ#yYWC!# z_=KvZd(5g&o(QfQVqo^5qSwW_HIFPJ_DwA}9pE=#7XV36>g~H*V%szR0(rVIel1P=X<~kmUyB^XlJl%1SEWC^) z_;ROYJ$sZ+V?=&?9i2uRq+D4<_RwJ4%=(pbf(V{4lfX$Xyd;=D#x7@qzPD*13@Swg zm>!Ep^^GCt_(RVhw+$3PB&ii8DcFv^eYu>xNP7|9)*EG(X%6VH9vJ3^WF9?o9kl@yovjTtb%;_@7uMeov~u{K~KddxEs|09?x8jl8*m@C~caUAhz^fr~m>~HHB z%gcDdF6;L$L3n}kj*4K3R*~uDGKV}e7JX-ABZ%jTB*9_xhkN&>24Hq2G6*T{R>BilK&BJIMS@iUSBXP!nF*fErbr{uv8u5QaTw=o_7ZqGo z3lvBA737~_$YPer#(PPX4z4z37|V`lET_x3`SLXR!C{t$RFc|{ETQ69$BPr*uagV( zT&gaV#uu%t0CXCmBg`ieqao1#0h`6J>sTouGN%y(sIr>kqJg^-6+lmAB4}X8j9=HR z9u@q|t%b{~d%>Ccuee!`Cr!hF)eju068(B~h&5S4^{m2`duoS+89H*X%8H34SO{yY#p*{DaF!wbu^4Do_ zgGSmj)LloUW7t)CchGyE^r3)!ydcwZ)jkD6a^JQZgOBgRDhm#>K0PlEF5_Yz5@mQYd|Li6cpMzIGb!jXaaIRI57r7*-@bH>d z|7;bjoOEu6EL*Eeo_g6-^M zO`g6q|75cQ;igZ4CH|IXB?V8k6f_~<@Ca$9Z3cXbGec#LQBezztt&^S=xAGe%?U6MKUIX^iZqYGJLSu z#*r_{^Q6rz~5tvu(n%CmdM)tzcbOCI}l{^XV1f5 z?@(M@ADP9gc)0=8-Ep3|Awsd;gsoabIA5QfKEvf;3N8_R~#) zqs&0<5yr~GtMLe%82$A0inO)GD9b^*gvt0r=pV|_8%1&u&jRrZkbA3j(~xKu2prv9Ta>c z2n62By{XZs424;ZH(wmiN4*hoVI;viuM*EoUq+ zM>eWue`aRUsk0b}6o2@(S3S`V$;8y6uz>kM|vrG-E6f|jDgC9#|;h36w066m!0<57*CakAK-{rhuyR=lai>ed{ zY{ipVWG#_AO#POR^YbL0HSB6k9wKvslyjI{;R(xbB9DU^+o3UcWl!$W z&*R)#N9<>UC3V5*P1xZ^?}e7C`RUwurB`2E5T##i7Gq^S-ihzW5oG3420j+Lj1hF6 zcalJ?*@uU#c+Iho3fcr^enPhkN7%JQ?1eYl#*rZwjzl>V;L-Sdh`lM6W-Oc3)nk^4LB*w06*G znNLdFYOBkEV>f(XgdeADz&8}nEtIvI$^_=fi~a)2RF@}3J`Y%r1@u>)j^cA%zy`e- zz)GAR5X?FNp_th*-Sab{C5~UgkKciMCZvVuktDnrNvNWX=rZl336JD4KKEie{~>7N zBFxw5gV_A0gK!d=fWssM+diWH*d>o+;&a}XCZA8N{CdUL@w^49H4OMyVao;m>-9G> z)72jN!0kG_CN!gn*7FC>seTo#kH!(}=@n44Y>v~vTMQPI^SkZGyUbKjb4h4DUKwQxm3wi(_gHdNj}wQ@Aje$VaWGeL zw*pYN7Z99)wvi*GoCJk9ws~mE$&v)e2nz2j=m_8uyCzB6C{pQIvp4QNb{b>-3$gdKj9mS#mIm&xdOCs@@3l@Ltt6y8lp`7Pc_^tU36!{I#hZNWQ8~!rHZ9657Fy zQUzJ2jrDhUTEw8z5onNgVLUk2BFPHeo#usG26l^;KLM(8z!!&?>Sq7T7{XY3An~dD z#4(G*eaTv~!h&+ws+QcdV3=E~7VA;ab%~&{3^#cmz}m%Fp@_Gb)%+26{N5r}%9w?9 zuBQu$Ys$+6MA>?@-Ru7|4Xws1M0-{oFmbsk;(|w0u(aivtMP z-gv@|0C%$9r}hL&NSHCHV%r1O&z{ROR4K)d6m+8(u;%TkI;W63*j&o^6tIxVxGHeLdPHOoatLJ zZ_<^F+bIZCrImLfu0LKpq$00Yp17v4HD&{qfMIC@Jdc`+K{2&{m0rtWm8l=RDyhD! zZ3>0z6YA+{X2fI0XjM?CR`lAZhjKzR^XES<6ty|*ydoVPRhLWYBn*TP2d==eFT#x< zU_nLvgsDxl!rqm0vCgnNVj+M&(HAnK4Ze>BK3cdfFf(&@s z^x8Y95wRQo1f+~(A9l3lB%YtzlpPixLFK6fl(nILU7z#e-t$(XwxYnsX&w2O**epl zXHHnziG0BAznMXh`<9Df?fo~MWmGb9IA6k}PrWa5XA^kUX&Yq|x<*q`C0e3vCbWdH7pb?Gv)8aFS8+ zTkwR>rU;@P2PQr}&V67_Xlzz52DMSjiRk;F)f&~I)LQ4L43YQ0asd0ho@hko5a&7r zJkEvx8Q~wm*A1QAv3xh93~nJFbH4kq*7_txvY1gW*!oHg8=nFg6F=?123zRRYY(Z( z9N;K5!t!(M9CW!Jr`*eT@V`NsbplbGsl!`R-!E#};|xJjvG7DFW(aA*hQ9bs=AkO0 z8+fRo)U88JluPCgMSA&|MO=^P65Azjl-W|X!vT~B&sMaQzf0la2mL}~O2u3jROCFcrbl&%&ZQRF=0hMPFJ#J?O z$HKd?!rOqUu>ZB!n!UUiZK|3Ktn{4gVk9r%mYoaJ*ZKn7GdtF(qp~-HmOJ4>`Y_0= z=m_GT%7qdOlE}Fs8Dfbwv2LnGZXxeFu#|O=z%qvT66fHQN>sIGU5E2iFdgA9jqV*eLve(Y(ir`v7?Q>8=&$J^}TPW1$2s$Z>aG77O&ZY^Tk((o1DaV zkcIW$QH<`ez13`8!+H9%93Z!;*kVBp0yHh~2SSvi)6*StyDfQwx?MPWcQD$arcz9t zq|f%w?;~~t3GU0!h4>}#y8eL_(9pPO5LvM5$GivgbLKAK>AV;t?LetkYuK|#U0|~jP$)SGC;ydN(suX#eyx=jEbK;F&4Z@S8luRpOFU% zWCFDp#-gQk7Opu!wFBGIhGGgWuVdouH1$OFnW|G@Wqs*jbglQZDC6@h2}+TPWrQIL z!7ZXXVo7vl;5`$4Jmga3tou9m8g+*W=9q~SLWN;!p^3&a)hW-~b&1j`uYU~`9ONlN zajwf;Cr70X1AxPV9ryzd5c4-?7Q`EJ$z5&^r-s=vuCc7kvcby@zuf+xQ_c%Qu$ z&AO>N1i79aZ|T%Mm4Yp}1sDZe)$u_y0$f--E%IaIxJ!f)$W`gp1L?lQvb%E;>zakB zns9jN&*~$^;>7(W{f0N)?(%uD+D&0sP$B57yH=(c`CgH5$kP#2yL`0>lyUauKM1yG z55k9BiR^QDxxGXazR}vwOP1iQaOt^o8mnvqiX$J;rtkA#5&>vXY^QX|!(?n(#{Att zn&nBzaAsN#6A*L|S~wwU2`o~dY&1OtviQvJXqohGiK*~oq)Jyu@bC>ujuBo_aEo(H zlC+oA2h5B|Zr4Mjum4QtMZm}y&X!Syony{jzG$3BXaXz9Hk8=LiO%K~NlJPmMIEhv zDQ5GP;F^EDFGm&N2SpMAs*FwS?L`^tbQ{q?icIoaQN)*k;lI#lT-zQtP7K`9WdaEV z$eGxk^V*N?M(a!r-ff65I?b2I`QWiKX=*(Y4VhiQ+C8SKw`HqTW-H~({yY{k71$L^ zsQq<&L(txWVFnQrIyc|!|2@fh@C+xOt*iS)>jGZ?wkTeiRZ(f)N z-sQ9+30x|B+vAxpxDeQ97OTD=GYgCt@-9aFP-h)nhiZ5a(nyv-_ literal 0 HcmV?d00001 diff --git a/go.mod b/go.mod index f0d17f2ad2..7a42294cae 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,9 @@ module github.com/nspcc-dev/neo-go require ( - github.com/chzyer/readline v1.5.0 - github.com/consensys/gnark v0.8.1 - github.com/consensys/gnark-crypto v0.9.2 + github.com/chzyer/readline v1.5.1 + github.com/consensys/gnark v0.9.0 + github.com/consensys/gnark-crypto v0.11.2 github.com/davecgh/go-spew v1.1.1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 github.com/google/uuid v1.3.0 @@ -30,7 +30,7 @@ require ( golang.org/x/crypto v0.12.0 golang.org/x/term v0.11.0 golang.org/x/text v0.12.0 - golang.org/x/tools v0.11.1 + golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 gopkg.in/yaml.v3 v3.0.1 ) @@ -38,17 +38,18 @@ require ( github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20221202181307-76fa05c21b12 // indirect github.com/benbjohnson/clock v1.1.0 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/bits-and-blooms/bitset v1.8.0 // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect github.com/frankban/quicktest v1.14.5 // indirect - github.com/fxamacker/cbor/v2 v2.4.0 // indirect + github.com/fxamacker/cbor/v2 v2.5.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.1 // indirect - github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect - github.com/mattn/go-colorable v0.1.12 // indirect - github.com/mattn/go-isatty v0.0.14 // indirect + github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/nspcc-dev/hrw v1.0.9 // indirect @@ -59,13 +60,13 @@ require ( github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.37.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect - github.com/rs/zerolog v1.29.0 // indirect + github.com/rs/zerolog v1.30.0 // indirect github.com/russross/blackfriday/v2 v2.0.1 // indirect github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/x448/float16 v0.8.4 // indirect go.uber.org/multierr v1.9.0 // indirect - golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b // indirect + golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect golang.org/x/mod v0.12.0 // indirect golang.org/x/net v0.14.0 // indirect golang.org/x/sync v0.3.0 // indirect diff --git a/go.sum b/go.sum index 97bc5169d2..50c270f28b 100644 --- a/go.sum +++ b/go.sum @@ -46,6 +46,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bits-and-blooms/bitset v1.8.0 h1:FD+XqgOZDUxxZ8hzoBFuV9+cGWY9CslN6d5MS5JVb4c= +github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -54,23 +56,23 @@ github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/logex v1.2.0 h1:+eqR0HfOetur4tgnC8ftU5imRnhi4te+BadWS95c5AM= -github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= +github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= +github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/readline v1.5.0 h1:lSwwFrbNviGePhkewF1az4oLmcwqCZijQ2/Wi3BGHAI= -github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= +github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= +github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/chzyer/test v0.0.0-20210722231415-061457976a23 h1:dZ0/VyGgQdVGAss6Ju0dt5P0QltE0SFY5Woh6hbIfiQ= -github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= +github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= -github.com/consensys/gnark v0.8.1 h1:zXM6iFejCJSwqkZsjS/qMQGLEyX0rg8nRhwuEwzj3bg= -github.com/consensys/gnark v0.8.1/go.mod h1:PsGdLgX5nBy9EsDbqBkvTncZbfT69MizMsveGAsHBbo= -github.com/consensys/gnark-crypto v0.9.2 h1:a4gsSAnQNgrt8dqxsd49H2rtLQPoekZCWpCmcKPRNus= -github.com/consensys/gnark-crypto v0.9.2/go.mod h1:a2DQL4+5ywF6safEeZFEPGRiiGbjzGFRUN2sg06VuU4= -github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/consensys/gnark v0.9.0 h1:OoOr0Q771mQINVdP3s1AF2Rs1y8gtXhWVkadz/9KmZc= +github.com/consensys/gnark v0.9.0/go.mod h1:Sy9jJjIaGJFfNeupyNOR9Ei2IbAB6cfCO78DfG27YvM= +github.com/consensys/gnark-crypto v0.11.2 h1:GJjjtWJ+db1xGao7vTsOgAOGgjfPe7eRGPL+xxMX0qE= +github.com/consensys/gnark-crypto v0.11.2/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -89,8 +91,8 @@ github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88= -github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= +github.com/fxamacker/cbor/v2 v2.5.0 h1:oHsG0V/Q6E/wqTS2O1Cozzsy69nqCiguo5Q1a1ADivE= +github.com/fxamacker/cbor/v2 v2.5.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -159,8 +161,8 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= +github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b h1:h9U78+dx9a4BKdQkBBos92HalKpaGKHrp+3Uo6yTodo= +github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= @@ -200,10 +202,13 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= -github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= @@ -280,11 +285,11 @@ github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.29.0 h1:Zes4hju04hjbvkVkOhdl2HpZa+0PmVwigmo8XoORE5w= -github.com/rs/zerolog v1.29.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c= +github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= @@ -347,8 +352,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b h1:r+vk0EmXNmekl0S0BascoeeoHk/L7wmaW2QF90K+kYI= -golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ= +golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -473,6 +478,8 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc 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.0.0-20220310020820-b874c991c1a5/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.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -531,8 +538,8 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.11.1 h1:ojD5zOW8+7dOGzdnNgersm8aPfcDjhMp12UfG93NIMc= -golang.org/x/tools v0.11.1/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8= +golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E= +golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/pkg/smartcontract/zkpbinding/binding.go b/pkg/smartcontract/zkpbinding/binding.go index 2af304898a..db19876f42 100644 --- a/pkg/smartcontract/zkpbinding/binding.go +++ b/pkg/smartcontract/zkpbinding/binding.go @@ -10,7 +10,6 @@ package zkpbinding import ( - "bytes" "encoding/binary" "errors" "fmt" @@ -21,6 +20,7 @@ import ( bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bn254/fr" "github.com/consensys/gnark/backend/groth16" + curve "github.com/consensys/gnark/backend/groth16/bls12-381" "github.com/consensys/gnark/backend/witness" "github.com/nspcc-dev/neo-go/pkg/util/slice" ) @@ -223,51 +223,17 @@ func GenerateVerifier(cfg Config) error { return fmt.Errorf("unexpected elliptic curve: %s", cfg.VerifyingKey.CurveID()) } - // Fetch the contract's public verification parameters. We can't directly access - // the VerifyingKey elements, because it's hidden under internal package, thus, - // take these parameters from the serialized VerifyingKey representation. It - // follows the bellman format: - // https://github.com/zkcrypto/bellman/blob/fa9be45588227a8c6ec34957de3f68705f07bd92/src/groth16/mod.rs#L143 - // [α]1,[β]1,[β]2,[γ]2,[δ]1,[δ]2,uint32(len(Kvk)),[Kvk]1 - // See also the serialisation code: https://github.com/Consensys/gnark/blob/165b49ab88d69c97867a76e147e6fd41af138210/internal/backend/bls12-381/groth16/marshal.go#L95 - var buf bytes.Buffer - _, err := cfg.VerifyingKey.WriteTo(&buf) - if err != nil { - return fmt.Errorf("failed to serialize verifying key: %w", err) - } - vkBytes := slice.Copy(buf.Bytes()) - - // Ensure the serialized verifier key has the expected length/format (just in case). - if len(vkBytes) < verifyingKeyConstantPartLen { - return errors.New("unexpected len of constant-size part of serialized verifying key") - } - kvkLen := binary.BigEndian.Uint32(vkBytes[verifyingKeyConstantPartLen-4:]) - if len(vkBytes) != verifyingKeyConstantPartLen+int(kvkLen*bls12381.SizeOfG1AffineCompressed) { - return errors.New("unexpected len of serialized verifying key") - } - - var ( - alphaG1Offset = 0 - betaG2Offset = bls12381.SizeOfG1AffineCompressed + bls12381.SizeOfG1AffineCompressed // [α]1,[β]1 - gammaG2Offset = bls12381.SizeOfG1AffineCompressed + bls12381.SizeOfG1AffineCompressed + // [α]1,[β]1 - bls12381.SizeOfG2AffineCompressed // [β]2 - deltaG2Offset = bls12381.SizeOfG1AffineCompressed + bls12381.SizeOfG1AffineCompressed + // [α]1,[β]1 - bls12381.SizeOfG2AffineCompressed + bls12381.SizeOfG2AffineCompressed + // [β]2,[γ]2 - bls12381.SizeOfG1AffineCompressed // [δ]1 - kvkLenOffset = bls12381.SizeOfG1AffineCompressed + bls12381.SizeOfG1AffineCompressed + // [α]1,[β]1 - bls12381.SizeOfG2AffineCompressed + bls12381.SizeOfG2AffineCompressed + // [β]2,[γ]2 - bls12381.SizeOfG1AffineCompressed + bls12381.SizeOfG2AffineCompressed // [δ]1,[δ]2 - kvkStartOffset = kvkLenOffset + 4 - ) - alphaG1 := vkBytes[alphaG1Offset : alphaG1Offset+bls12381.SizeOfG1AffineCompressed] - betaG2 := vkBytes[betaG2Offset : betaG2Offset+bls12381.SizeOfG2AffineCompressed] - gammaG2 := vkBytes[gammaG2Offset : gammaG2Offset+bls12381.SizeOfG2AffineCompressed] - deltaG2 := vkBytes[deltaG2Offset : deltaG2Offset+bls12381.SizeOfG2AffineCompressed] - kvks := make([][]byte, kvkLen) + // Fetch the contract's public verification parameters. We can directly access + // the VerifyingKey elements since gnark v0.9.0. + vk := cfg.VerifyingKey.(*curve.VerifyingKey) + alphaG1 := vk.G1.Alpha.Bytes() + betaG2 := vk.G2.Beta.Bytes() + gammaG2 := vk.G2.Gamma.Bytes() + deltaG2 := vk.G2.Delta.Bytes() + kvks := make([][]byte, len(vk.G1.K)) for i := range kvks { - start := kvkStartOffset + i*bls12381.SizeOfG1AffineCompressed - end := start + bls12381.SizeOfG1AffineCompressed - kvks[i] = vkBytes[start:end] + arr := vk.G1.K[i].Bytes() + kvks[i] = arr[:] } // Generate verification contract from the template using the retrieved @@ -276,11 +242,11 @@ func GenerateVerifier(cfg Config) error { "byteSliceToStr": byteSliceToStr, }).Parse(goVerificationTmpl)) - err = tmpl.Execute(cfg.Output, tmplParams{ - Alpha: alphaG1, - Beta: betaG2, - Gamma: gammaG2, - Delta: deltaG2, + err := tmpl.Execute(cfg.Output, tmplParams{ + Alpha: alphaG1[:], + Beta: betaG2[:], + Gamma: gammaG2[:], + Delta: deltaG2[:], ICs: kvks, }) if err != nil { @@ -334,20 +300,10 @@ func GetVerifyProofArgs(proof groth16.Proof, publicWitness witness.Witness) (*Ve return nil, fmt.Errorf("failed to retrieve public witness: %w", err) } // Get the proof bytes (points are in the compressed form, as Verification contract accepts it). - proofSizeCompressed := int64(bls12381.SizeOfG1AffineCompressed + bls12381.SizeOfG2AffineCompressed + bls12381.SizeOfG1AffineCompressed) - var buf bytes.Buffer - n, err := proof.WriteTo(&buf) - if err != nil { - return nil, fmt.Errorf("failed to serialize proof: %w", err) - } - if n != proofSizeCompressed { - return nil, fmt.Errorf("unexpected serialized proof length: %d", n) - } - proofBytes := slice.Copy(buf.Bytes()) - - aBytes := proofBytes[:bls12381.SizeOfG1AffineCompressed] - bBytes := proofBytes[bls12381.SizeOfG1AffineCompressed : bls12381.SizeOfG1AffineCompressed+bls12381.SizeOfG2AffineCompressed] - cBytes := proofBytes[bls12381.SizeOfG1AffineCompressed+bls12381.SizeOfG2AffineCompressed:] + p := proof.(*curve.Proof) + aBytes := p.Ar.Bytes() + bBytes := p.Bs.Bytes() + cBytes := p.Krs.Bytes() publicWitnessBytes, err := publicWitness.MarshalBinary() if err != nil { @@ -375,9 +331,9 @@ func GetVerifyProofArgs(proof groth16.Proof, publicWitness witness.Witness) (*Ve input[i] = publicWitnessBytes[start:end] } return &VerifyProofArgs{ - A: aBytes, - B: bBytes, - C: cBytes, + A: aBytes[:], + B: bBytes[:], + C: cBytes[:], PublicWitnesses: input, }, nil }