Stub out algorand support in wormhole (#611)

* Stub out algorand support in wormhole

  1) Introduce the algorand chain constant in all the appropriate places
  2) Deploy pyth/hernandc algorand smart contracts into devnet
  3) Fund all the correct contracts for devnet testing

Change-Id: I6e4402b5b21223b32ea89653f8c7606f5c7f2843

* pr/jsiegel/algorand-v1: ALGORAND is not a EVM chain @ gusc1a-ossdev-jsl1

* pr/jsiegel/algorand-v1: fix lint @ gusc1a-ossdev-jsl1

* pr/jsiegel/algorand-v1: put the requirements into the image @ gusc1a-ossdev-jsl1

* jsiegel/algorand: make the watcher hang forever @ gusc1a-ossdev-jsl1

* jsiegel/algorand: comment these out @ gusc1a-ossdev-jsl1

* jsiegel/algorand: put this back in @ gusc1a-ossdev-jsl1

* jsiegel/algorand: fix guardian example @ gusc1a-ossdev-jsl1

* Generate teal source code

commit-id:a537a109

* jsiegel/algorand: it builds @ gusc1a-ossdev-jsl1

* pr/jsiegel/algorand-v1: add Dockerfile.teal @ gusc1a-ossdev-jsl1

* jsiegel/algorand: improve the dependencies @ gusc1a-ossdev-jsl1

* pr/jsiegel/algorand-v1: Fix up build @ gusc1a-ossdev-jsl1

* dead file

* pr/jsiegel/algorand-v1: remove more stuff @ gusc1a-ossdev-jsl1

* pr/jsiegel/algorand-v1: fix build @ gusc1a-ossdev-jsl1

* pr/jsiegel/algorand-v1: freeze the requirements @ gusc1a-ossdev-jsl1

* pr/jsiegel/algorand-v1: Fix teal to use pipenv @ gusc1a-ossdev-jsl1

* pr/jsiegel/algorand-v1: fix miss-merge @ gusc1a-ossdev-jsl1

Co-authored-by: Leo <leo@certus.one>
This commit is contained in:
jumpsiegel 2021-12-22 10:22:04 -06:00 committed by GitHub
parent d6945bf6fa
commit f90ed66ca0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 711 additions and 4 deletions

View File

@ -182,3 +182,7 @@ Node logs:
Account list:
kubectl exec -c goal-kmd algorand-0 -- ./goal account list
Get yourself a working shell:
kubectl exec -c goal-kmd algorand-0 -it shell-demo -- /bin/bash

21
Dockerfile.teal Normal file
View File

@ -0,0 +1,21 @@
# syntax=docker.io/docker/dockerfile:1.3@sha256:42399d4635eddd7a9b8a24be879d2f9a930d0ed040a61324cfdf59ef1357b3b2
FROM docker.io/fedora:34 AS teal-build
RUN dnf -y install python3-pip
COPY staging/algorand/teal /teal
# Install pyTEAL dependencies
COPY third_party/algorand/Pipfile.lock Pipfile.lock
COPY third_party/algorand/Pipfile Pipfile
RUN pip install pipenv
RUN pipenv install
# Regenerate TEAL assembly
RUN pipenv run python3 /teal/wormhole/pyteal/vaa-processor.py vaa-processor-approval.teal vaa-processor-clear.teal
RUN pipenv run python3 /teal/wormhole/pyteal/vaa-verify.py 0 vaa-verify.teal
FROM scratch AS teal-export
COPY --from=teal-build /vaa-processor-approval.teal third_party/algorand/teal/
COPY --from=teal-build /vaa-processor-clear.teal third_party/algorand/teal/
COPY --from=teal-build /vaa-verify.teal third_party/algorand/teal/

View File

@ -86,6 +86,14 @@ local_resource(
trigger_mode = trigger_mode,
)
local_resource(
name = "teal-gen",
deps = ["staging/algorand/teal"],
cmd = "tilt docker build -- --target teal-export -f Dockerfile.teal -o type=local,dest=. .",
env = {"DOCKER_BUILDKIT": "1"},
trigger_mode = trigger_mode,
)
# wasm
local_resource(
@ -301,6 +309,7 @@ docker_build(
k8s_resource(
"algorand",
resource_deps = ["teal-gen"],
port_forwards = [
port_forward(4001, name = "Algorand RPC [:4001]", host = webHost),
port_forward(4002, name = "Algorand KMD [:4002]", host = webHost),

View File

@ -52,7 +52,7 @@ spec:
command:
- /bin/sh
- -c
- ./goal kmd start -d /network/Node && ./goal account list && sleep infinity
- ./goal kmd start -d /network/Node && ./goal account list && /setup/setup.sh && sleep infinity
ports:
- containerPort: 4002
name: kmd

View File

@ -94,6 +94,12 @@ spec:
- http://terra-lcd:1317
- --terraContract
- terra18vd8fpwxzck93qlwghaj6arh4p7c5n896xzem5
- --algorandRPC
- http://localhost:4001
- --algorandToken
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
- --algorandContract
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
- --solanaContract
- Bridge1p5gheXUvJ6jGWGeCsgPKgnE3YgdGKRVCMY9o
- --solanaWS

View File

@ -37,6 +37,8 @@ import (
"github.com/certusone/wormhole/node/pkg/terra"
"github.com/certusone/wormhole/node/pkg/algorand"
ipfslog "github.com/ipfs/go-log/v2"
)
@ -78,6 +80,10 @@ var (
terraLCD *string
terraContract *string
algorandRPC *string
algorandToken *string
algorandContract *string
solanaWsRPC *string
solanaRPC *string
@ -145,6 +151,10 @@ func init() {
terraLCD = NodeCmd.Flags().String("terraLCD", "", "Path to LCD service root for http calls")
terraContract = NodeCmd.Flags().String("terraContract", "", "Wormhole contract address on Terra blockchain")
algorandRPC = NodeCmd.Flags().String("algorandRPC", "", "Algorand RPC URL")
algorandToken = NodeCmd.Flags().String("algorandToken", "", "Algorand access token")
algorandContract = NodeCmd.Flags().String("algorandContract", "", "Algorand contract")
solanaWsRPC = NodeCmd.Flags().String("solanaWS", "", "Solana Websocket URL (required")
solanaRPC = NodeCmd.Flags().String("solanaRPC", "", "Solana RPC URL (required")
@ -248,6 +258,9 @@ func runNode(cmd *cobra.Command, args []string) {
readiness.RegisterComponent(common.ReadinessEthSyncing)
readiness.RegisterComponent(common.ReadinessSolanaSyncing)
readiness.RegisterComponent(common.ReadinessTerraSyncing)
if *unsafeDevMode {
readiness.RegisterComponent(common.ReadinessAlgorandSyncing)
}
readiness.RegisterComponent(common.ReadinessBSCSyncing)
readiness.RegisterComponent(common.ReadinessPolygonSyncing)
readiness.RegisterComponent(common.ReadinessAvalancheSyncing)
@ -384,6 +397,18 @@ func runNode(cmd *cobra.Command, args []string) {
logger.Fatal("Please specify --terraContract")
}
if *unsafeDevMode {
if *algorandRPC == "" {
logger.Fatal("Please specify --algorandRPC")
}
if *algorandToken == "" {
logger.Fatal("Please specify --algorandToken")
}
if *algorandContract == "" {
logger.Fatal("Please specify --algorandContract")
}
}
if *bigTablePersistenceEnabled {
if *bigTableGCPProject == "" {
logger.Fatal("Please specify --bigTableGCPProject")
@ -585,6 +610,13 @@ func runNode(cmd *cobra.Command, args []string) {
return err
}
if *unsafeDevMode {
if err := supervisor.Run(ctx, "algorandwatch",
algorand.NewWatcher(*algorandRPC, *algorandToken, *algorandContract, lockC, setC).Run); err != nil {
return err
}
}
if err := supervisor.Run(ctx, "solwatch-confirmed",
solana.NewSolanaWatcher(*solanaWsRPC, *solanaRPC, solAddress, lockC, rpc.CommitmentConfirmed).Run); err != nil {
return err

View File

@ -0,0 +1,30 @@
package algorand
import (
"context"
"github.com/certusone/wormhole/node/pkg/common"
"github.com/certusone/wormhole/node/pkg/readiness"
)
type (
// Watcher is responsible for looking over Algorand blockchain and reporting new transactions to the contract
Watcher struct {
urlRPC string
urlToken string
contract string
msgChan chan *common.MessagePublication
setChan chan *common.GuardianSet
}
)
// NewWatcher creates a new Algorand contract watcher
func NewWatcher(urlRPC string, urlToken string, contract string, lockEvents chan *common.MessagePublication, setEvents chan *common.GuardianSet) *Watcher {
return &Watcher{urlRPC: urlRPC, urlToken: urlToken, contract: contract, msgChan: lockEvents, setChan: setEvents}
}
func (e *Watcher) Run(ctx context.Context) error {
readiness.SetReady(common.ReadinessAlgorandSyncing)
select {}
}

View File

@ -6,6 +6,7 @@ const (
ReadinessEthSyncing readiness.Component = "ethSyncing"
ReadinessSolanaSyncing readiness.Component = "solanaSyncing"
ReadinessTerraSyncing readiness.Component = "terraSyncing"
ReadinessAlgorandSyncing readiness.Component = "algorandSyncing"
ReadinessBSCSyncing readiness.Component = "bscSyncing"
ReadinessPolygonSyncing readiness.Component = "polygonSyncing"
ReadinessEthRopstenSyncing readiness.Component = "ethRopstenSyncing"

View File

@ -98,6 +98,8 @@ func (c ChainID) String() string {
return "avalanche"
case ChainIDOasis:
return "oasis"
case ChainIDAlgorand:
return "algorand"
case ChainIDEthereumRopsten:
return "ethereum-ropsten"
default:
@ -123,6 +125,8 @@ func ChainIDFromString(s string) (ChainID, error) {
return ChainIDAvalanche, nil
case "oasis":
return ChainIDOasis, nil
case "algorand":
return ChainIDAlgorand, nil
case "ethereum-ropsten":
return ChainIDEthereumRopsten, nil
default:
@ -146,6 +150,8 @@ const (
ChainIDAvalanche ChainID = 6
// ChainIDOasis is the ChainID of Oasis
ChainIDOasis ChainID = 7
// ChainIDAlgorand is the ChainID of Algorand
ChainIDAlgorand ChainID = 8
// ChainIDEthereumRopsten is the ChainID of Ethereum Ropsten
ChainIDEthereumRopsten ChainID = 10001

View File

@ -16,6 +16,7 @@ enum ChainID {
CHAIN_ID_POLYGON = 5;
CHAIN_ID_AVALANCHE = 6;
CHAIN_ID_OASIS = 7;
CHAIN_ID_ALGORAND = 8;
// Special case - Eth has two testnets. CHAIN_ID_ETHEREUM is Goerli,
// but we also want to connect to Ropsten, so we add a separate chain.
CHAIN_ID_ETHEREUM_ROPSTEN = 10001;

View File

@ -1,4 +1,4 @@
export type ChainId = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10001;
export type ChainId = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10001;
export const CHAIN_ID_SOLANA: ChainId = 1;
export const CHAIN_ID_ETH: ChainId = 2;
export const CHAIN_ID_TERRA: ChainId = 3;
@ -6,6 +6,7 @@ export const CHAIN_ID_BSC: ChainId = 4;
export const CHAIN_ID_POLYGON: ChainId = 5;
export const CHAIN_ID_AVAX: ChainId = 6;
export const CHAIN_ID_OASIS: ChainId = 7;
export const CHAIN_ID_ALGORAND: ChainId = 8;
export const CHAIN_ID_ETHEREUM_ROPSTEN: ChainId = 10001;
export const WSOL_ADDRESS = "So11111111111111111111111111111111111111112";

0
staging/algorand/scripts/createapp.sh Normal file → Executable file
View File

View File

@ -120,10 +120,10 @@ if __name__ == "__main__":
print("VAA Verify Stateless Program, (c) 2021-22 Randlabs Inc. ")
print("Compiling...")
if len(sys.argv) >= 2:
if len(sys.argv) >= 1:
appid = sys.argv[1]
if len(sys.argv) >= 3:
if len(sys.argv) >= 2:
outfile = sys.argv[2]
with open(outfile, "w") as f:

2
third_party/algorand/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
# Generated
teal

View File

@ -3,6 +3,11 @@ FROM docker.io/algorand/stable:3.2.1@sha256:0a87978492680fd98e2cc410f59f2bfd7fef
RUN mkdir -p /setup
ADD template.json /setup/
ADD setup.sh /setup/
ADD setup.py /setup/
ADD teal/vaa-verify.teal /setup/
ADD teal/vaa-processor-clear.teal /setup/
ADD teal/vaa-processor-approval.teal /setup/
RUN ./goal network create -n sandnet -r /network -t /setup/template.json && echo rawr
@ -14,3 +19,9 @@ ADD config.json /network/Node/config.json
ADD kmd_config.json /network/Node/kmd-v0.5/kmd_config.json
ENV ALGORAND_DATA=/network/Node
ADD Pipfile.lock /setup/
ADD Pipfile /setup/
RUN apt-get update
RUN apt-get install -y python3-pip
RUN pip install pipenv

12
third_party/algorand/Pipfile vendored Normal file
View File

@ -0,0 +1,12 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
py-algorand-sdk = "*"
pyteal = "*"
mypy = "*"
pytest = "*"
[dev-packages]

316
third_party/algorand/Pipfile.lock generated vendored Normal file
View File

@ -0,0 +1,316 @@
{
"_meta": {
"hash": {
"sha256": "7d3b87829ef46d00b82e4450cc45b6ca299dc0a5e9bba990744eda1c901d8af4"
},
"pipfile-spec": 6,
"requires": {},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"attrs": {
"hashes": [
"sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1",
"sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==21.2.0"
},
"cffi": {
"hashes": [
"sha256:00c878c90cb53ccfaae6b8bc18ad05d2036553e6d9d1d9dbcf323bbe83854ca3",
"sha256:0104fb5ae2391d46a4cb082abdd5c69ea4eab79d8d44eaaf79f1b1fd806ee4c2",
"sha256:06c48159c1abed75c2e721b1715c379fa3200c7784271b3c46df01383b593636",
"sha256:0808014eb713677ec1292301ea4c81ad277b6cdf2fdd90fd540af98c0b101d20",
"sha256:10dffb601ccfb65262a27233ac273d552ddc4d8ae1bf93b21c94b8511bffe728",
"sha256:14cd121ea63ecdae71efa69c15c5543a4b5fbcd0bbe2aad864baca0063cecf27",
"sha256:17771976e82e9f94976180f76468546834d22a7cc404b17c22df2a2c81db0c66",
"sha256:181dee03b1170ff1969489acf1c26533710231c58f95534e3edac87fff06c443",
"sha256:23cfe892bd5dd8941608f93348c0737e369e51c100d03718f108bf1add7bd6d0",
"sha256:263cc3d821c4ab2213cbe8cd8b355a7f72a8324577dc865ef98487c1aeee2bc7",
"sha256:2756c88cbb94231c7a147402476be2c4df2f6078099a6f4a480d239a8817ae39",
"sha256:27c219baf94952ae9d50ec19651a687b826792055353d07648a5695413e0c605",
"sha256:2a23af14f408d53d5e6cd4e3d9a24ff9e05906ad574822a10563efcef137979a",
"sha256:31fb708d9d7c3f49a60f04cf5b119aeefe5644daba1cd2a0fe389b674fd1de37",
"sha256:3415c89f9204ee60cd09b235810be700e993e343a408693e80ce7f6a40108029",
"sha256:3773c4d81e6e818df2efbc7dd77325ca0dcb688116050fb2b3011218eda36139",
"sha256:3b96a311ac60a3f6be21d2572e46ce67f09abcf4d09344c49274eb9e0bf345fc",
"sha256:3f7d084648d77af029acb79a0ff49a0ad7e9d09057a9bf46596dac9514dc07df",
"sha256:41d45de54cd277a7878919867c0f08b0cf817605e4eb94093e7516505d3c8d14",
"sha256:4238e6dab5d6a8ba812de994bbb0a79bddbdf80994e4ce802b6f6f3142fcc880",
"sha256:45db3a33139e9c8f7c09234b5784a5e33d31fd6907800b316decad50af323ff2",
"sha256:45e8636704eacc432a206ac7345a5d3d2c62d95a507ec70d62f23cd91770482a",
"sha256:4958391dbd6249d7ad855b9ca88fae690783a6be9e86df65865058ed81fc860e",
"sha256:4a306fa632e8f0928956a41fa8e1d6243c71e7eb59ffbd165fc0b41e316b2474",
"sha256:57e9ac9ccc3101fac9d6014fba037473e4358ef4e89f8e181f8951a2c0162024",
"sha256:59888172256cac5629e60e72e86598027aca6bf01fa2465bdb676d37636573e8",
"sha256:5e069f72d497312b24fcc02073d70cb989045d1c91cbd53979366077959933e0",
"sha256:64d4ec9f448dfe041705426000cc13e34e6e5bb13736e9fd62e34a0b0c41566e",
"sha256:6dc2737a3674b3e344847c8686cf29e500584ccad76204efea14f451d4cc669a",
"sha256:74fdfdbfdc48d3f47148976f49fab3251e550a8720bebc99bf1483f5bfb5db3e",
"sha256:75e4024375654472cc27e91cbe9eaa08567f7fbdf822638be2814ce059f58032",
"sha256:786902fb9ba7433aae840e0ed609f45c7bcd4e225ebb9c753aa39725bb3e6ad6",
"sha256:8b6c2ea03845c9f501ed1313e78de148cd3f6cad741a75d43a29b43da27f2e1e",
"sha256:91d77d2a782be4274da750752bb1650a97bfd8f291022b379bb8e01c66b4e96b",
"sha256:91ec59c33514b7c7559a6acda53bbfe1b283949c34fe7440bcf917f96ac0723e",
"sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954",
"sha256:a5263e363c27b653a90078143adb3d076c1a748ec9ecc78ea2fb916f9b861962",
"sha256:abb9a20a72ac4e0fdb50dae135ba5e77880518e742077ced47eb1499e29a443c",
"sha256:c2051981a968d7de9dd2d7b87bcb9c939c74a34626a6e2f8181455dd49ed69e4",
"sha256:c21c9e3896c23007803a875460fb786118f0cdd4434359577ea25eb556e34c55",
"sha256:c2502a1a03b6312837279c8c1bd3ebedf6c12c4228ddbad40912d671ccc8a962",
"sha256:d4d692a89c5cf08a8557fdeb329b82e7bf609aadfaed6c0d79f5a449a3c7c023",
"sha256:da5db4e883f1ce37f55c667e5c0de439df76ac4cb55964655906306918e7363c",
"sha256:e7022a66d9b55e93e1a845d8c9eba2a1bebd4966cd8bfc25d9cd07d515b33fa6",
"sha256:ef1f279350da2c586a69d32fc8733092fd32cc8ac95139a00377841f59a3f8d8",
"sha256:f54a64f8b0c8ff0b64d18aa76675262e1700f3995182267998c31ae974fbc382",
"sha256:f5c7150ad32ba43a07c4479f40241756145a1f03b43480e058cfd862bf5041c7",
"sha256:f6f824dc3bce0edab5f427efcfb1d63ee75b6fcb7282900ccaf925be84efb0fc",
"sha256:fd8a250edc26254fe5b33be00402e6d287f562b6a5b2152dec302fa15bb3e997",
"sha256:ffaa5c925128e29efbde7301d8ecaf35c8c60ffbcd6a1ffd3a552177c8e5e796"
],
"version": "==1.15.0"
},
"iniconfig": {
"hashes": [
"sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3",
"sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"
],
"version": "==1.1.1"
},
"msgpack": {
"hashes": [
"sha256:0d8c332f53ffff01953ad25131272506500b14750c1d0ce8614b17d098252fbc",
"sha256:1c58cdec1cb5fcea8c2f1771d7b5fec79307d056874f746690bd2bdd609ab147",
"sha256:2c3ca57c96c8e69c1a0d2926a6acf2d9a522b41dc4253a8945c4c6cd4981a4e3",
"sha256:2f30dd0dc4dfe6231ad253b6f9f7128ac3202ae49edd3f10d311adc358772dba",
"sha256:2f97c0f35b3b096a330bb4a1a9247d0bd7e1f3a2eba7ab69795501504b1c2c39",
"sha256:36a64a10b16c2ab31dcd5f32d9787ed41fe68ab23dd66957ca2826c7f10d0b85",
"sha256:3d875631ecab42f65f9dce6f55ce6d736696ced240f2634633188de2f5f21af9",
"sha256:40fb89b4625d12d6027a19f4df18a4de5c64f6f3314325049f219683e07e678a",
"sha256:47d733a15ade190540c703de209ffbc42a3367600421b62ac0c09fde594da6ec",
"sha256:494471d65b25a8751d19c83f1a482fd411d7ca7a3b9e17d25980a74075ba0e88",
"sha256:51fdc7fb93615286428ee7758cecc2f374d5ff363bdd884c7ea622a7a327a81e",
"sha256:6eef0cf8db3857b2b556213d97dd82de76e28a6524853a9beb3264983391dc1a",
"sha256:6f4c22717c74d44bcd7af353024ce71c6b55346dad5e2cc1ddc17ce8c4507c6b",
"sha256:73a80bd6eb6bcb338c1ec0da273f87420829c266379c8c82fa14c23fb586cfa1",
"sha256:89908aea5f46ee1474cc37fbc146677f8529ac99201bc2faf4ef8edc023c2bf3",
"sha256:8a3a5c4b16e9d0edb823fe54b59b5660cc8d4782d7bf2c214cb4b91a1940a8ef",
"sha256:96acc674bb9c9be63fa8b6dabc3248fdc575c4adc005c440ad02f87ca7edd079",
"sha256:973ad69fd7e31159eae8f580f3f707b718b61141838321c6fa4d891c4a2cca52",
"sha256:9b6f2d714c506e79cbead331de9aae6837c8dd36190d02da74cb409b36162e8a",
"sha256:9c0903bd93cbd34653dd63bbfcb99d7539c372795201f39d16fdfde4418de43a",
"sha256:9fce00156e79af37bb6db4e7587b30d11e7ac6a02cb5bac387f023808cd7d7f4",
"sha256:a598d0685e4ae07a0672b59792d2cc767d09d7a7f39fd9bd37ff84e060b1a996",
"sha256:b0a792c091bac433dfe0a70ac17fc2087d4595ab835b47b89defc8bbabcf5c73",
"sha256:bb87f23ae7d14b7b3c21009c4b1705ec107cb21ee71975992f6aca571fb4a42a",
"sha256:bf1e6bfed4860d72106f4e0a1ab519546982b45689937b40257cfd820650b920",
"sha256:c1ba333b4024c17c7591f0f372e2daa3c31db495a9b2af3cf664aef3c14354f7",
"sha256:c2140cf7a3ec475ef0938edb6eb363fa704159e0bf71dde15d953bacc1cf9d7d",
"sha256:c7e03b06f2982aa98d4ddd082a210c3db200471da523f9ac197f2828e80e7770",
"sha256:d02cea2252abc3756b2ac31f781f7a98e89ff9759b2e7450a1c7a0d13302ff50",
"sha256:da24375ab4c50e5b7486c115a3198d207954fe10aaa5708f7b65105df09109b2",
"sha256:e4c309a68cb5d6bbd0c50d5c71a25ae81f268c2dc675c6f4ea8ab2feec2ac4e2",
"sha256:f01b26c2290cbd74316990ba84a14ac3d599af9cebefc543d241a66e785cf17d",
"sha256:f201d34dc89342fabb2a10ed7c9a9aaaed9b7af0f16a5923f1ae562b31258dea",
"sha256:f74da1e5fcf20ade12c6bf1baa17a2dc3604958922de8dc83cbe3eff22e8b611"
],
"version": "==1.0.3"
},
"mypy": {
"hashes": [
"sha256:13b3c110309b53f5a62aa1b360f598124be33a42563b790a2a9efaacac99f1fc",
"sha256:140174e872d20d4768124a089b9f9fc83abd6a349b7f8cc6276bc344eb598922",
"sha256:31895b0b3060baf15bf76e789d94722c026f673b34b774bba9e8772295edccff",
"sha256:331a81d2c9bf1be25317260a073b41f4584cd11701a7c14facef0aa5a005e843",
"sha256:40cb062f1b7ff4cd6e897a89d8ddc48c6ad7f326b5277c93a8c559564cc1551c",
"sha256:41f3575b20714171c832d8f6c7aaaa0d499c9a2d1b8adaaf837b4c9065c38540",
"sha256:431be889ffc8d9681813a45575c42e341c19467cbfa6dd09bf41467631feb530",
"sha256:562a0e335222d5bbf5162b554c3afe3745b495d67c7fe6f8b0d1b5bace0c1eeb",
"sha256:618e677aabd21f30670bffb39a885a967337f5b112c6fb7c79375e6dced605d6",
"sha256:69b5a835b12fdbfeed84ef31152d41343d32ccb2b345256d8682324409164330",
"sha256:71c77bd885d2ce44900731d4652d0d1c174dc66a0f11200e0c680bdedf1a6b37",
"sha256:82e6c15675264e923b60a11d6eb8f90665504352e68edfbb4a79aac7a04caddd",
"sha256:98b4f91a75fed2e4c6339e9047aba95968d3a7c4b91e92ab9dc62c0c583564f4",
"sha256:993c2e52ea9570e6e872296c046c946377b9f5e89eeb7afea2a1524cf6e50b27",
"sha256:9cd316e9705555ca6a50670ba5fb0084d756d1d8cb1697c83820b1456b0bc5f3",
"sha256:a55438627f5f546192f13255a994d6d1cf2659df48adcf966132b4379fd9c86b",
"sha256:df0fec878ccfcb2d1d2306ba31aa757848f681e7bbed443318d9bbd4b0d0fe9a",
"sha256:e091fe58b4475b3504dc7c3022ff7f4af2f9e9ddf7182047111759ed0973bbde",
"sha256:f8b2059f73878e92eff7ed11a03515d6572f4338a882dd7547b5f7dd242118e6",
"sha256:ffb1e57ec49a30e3c0ebcfdc910ae4aceb7afb649310b7355509df6b15bd75f6"
],
"index": "pypi",
"version": "==0.920"
},
"mypy-extensions": {
"hashes": [
"sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d",
"sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"
],
"version": "==0.4.3"
},
"packaging": {
"hashes": [
"sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb",
"sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"
],
"markers": "python_version >= '3.6'",
"version": "==21.3"
},
"pluggy": {
"hashes": [
"sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159",
"sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"
],
"markers": "python_version >= '3.6'",
"version": "==1.0.0"
},
"py": {
"hashes": [
"sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719",
"sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==1.11.0"
},
"py-algorand-sdk": {
"hashes": [
"sha256:110480dc5baf2102721a5fe860c22fb445a737dfbb0a2e82ed97fee03b792d19",
"sha256:691771118f88855affbb57853a73113ce0ea554d7b9f1bbe50e309a83a632158"
],
"index": "pypi",
"version": "==1.8.0"
},
"pycparser": {
"hashes": [
"sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9",
"sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"
],
"version": "==2.21"
},
"pycryptodomex": {
"hashes": [
"sha256:08c809e9f4be8d4f9948cf4d5ebc7431bbd9e1c0cd5ff478d0d5229f1bc4ad50",
"sha256:097095a7c24b9e7eec865417f620f78adf218162c03b68e4fde194bf87801a67",
"sha256:0981e8071d2ee457d842821438f833e362eed9a25a445d54ad7610b24293118f",
"sha256:1bd9d158afa33dca04748b23e7b9d4055f8c8015ace2e972a866519af02d5eed",
"sha256:1f6c370abf11546b1c9b70062918d601ac8fb7ff113554601b43175eed7480ef",
"sha256:2595b7be43b8b2da953ea3506a8d71c07fc9b479d5c118b0c44a5eca2a1664f6",
"sha256:2d173a5db4e306cd32558b1a3ceb45bd2ebeb6596525fd5945963798b3851e3d",
"sha256:33c06d6819a0204fac675d100f92aa472c704cd774a47171a5949c75c1040ed6",
"sha256:3559da56e1045ad567e69fcc74245073fe1943b07b137bfd1073c7a540a89df7",
"sha256:3bfa2936f8391bfaa17ed6a5c726e33acad56d7b47b8bf824b1908b16b140025",
"sha256:4361881388817f89aa819a553e987200a6eb664df995632b063997dd373a7cee",
"sha256:43af464dcac1ae53e6e14a0ae6f08373b538f3c49fb9e426423618571edfecff",
"sha256:44097663c62b3aa03b5b403b816dedafa592984e8c6857a061ade41f32a2666e",
"sha256:4cbaea8ab8bfa283e6219af39624d921f72f8174765a35416aab4d4b4dec370e",
"sha256:5b0fd9fc81d43cd54dc8e4b2df8730ffd1e34f1f0679920deae16f6487aa1414",
"sha256:676d9f4286f490612fa35ca8fe4b1fced8ff18e653abc1dda34fbf166129d6c2",
"sha256:79ad48096ceb5c714fbc4dc82e3e6b37f095f627b1fef90d94d85e19a19d6611",
"sha256:83379f1fd7b99c4993f5e905f2a6ddb9003996655151ea3c2ee77332ad009d08",
"sha256:88dc997e3e9199a0d67b547fba36c6d1c54fca7d83c4bfe0d3f34f55a4717a2c",
"sha256:8c5b97953130ff76500c6e8e159f2b881c737ebf00034006517b57f382d5317c",
"sha256:922e9dac0166e4617e5c7980d2cff6912a6eb5cb5c13e7ece222438650bd7f66",
"sha256:9c037aaf6affc8f7c4f6f9f6279aa57dd526734246fb5221a0fff3124f57e0b1",
"sha256:a896b41c518269c1cceb582e298a868e6c74bb3cbfd362865ea686c78aebe91d",
"sha256:b1a6f17c4ad896ed628663b021cd797b098c7e9537fd259958f6ffb3b8921081",
"sha256:b5ddaee74e1f06af9c0765a147904dddacf4ca9707f8f079e14e2b14b4f5a544",
"sha256:d55374ebc36de7a3217f2e2318886f0801dd5e486e21aba1fc4ca08e3b6637d7",
"sha256:ddac6a092b97aa11d2a21aec33e941b4453ef774da3d98f2b7c1e01da05e6d5e",
"sha256:de9832ac3c51484fe1757ca4303695423b16cfa54874dae9239bf41f50a2affa",
"sha256:e42a82c63952ed70be3c13782c6984a519b514e6b10108a9647c7576b6c86650",
"sha256:ea8e83bf4731a2369350d7771a1f2ef8d72ad3da70a37d86b1374be8c675abd0"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==3.12.0"
},
"pynacl": {
"hashes": [
"sha256:06cbb4d9b2c4bd3c8dc0d267416aaed79906e7b33f114ddbf0911969794b1cc4",
"sha256:11335f09060af52c97137d4ac54285bcb7df0cef29014a1a4efe64ac065434c4",
"sha256:2fe0fc5a2480361dcaf4e6e7cea00e078fcda07ba45f811b167e3f99e8cff574",
"sha256:30f9b96db44e09b3304f9ea95079b1b7316b2b4f3744fe3aaecccd95d547063d",
"sha256:4e10569f8cbed81cb7526ae137049759d2a8d57726d52c1a000a3ce366779634",
"sha256:511d269ee845037b95c9781aa702f90ccc36036f95d0f31373a6a79bd8242e25",
"sha256:537a7ccbea22905a0ab36ea58577b39d1fa9b1884869d173b5cf111f006f689f",
"sha256:54e9a2c849c742006516ad56a88f5c74bf2ce92c9f67435187c3c5953b346505",
"sha256:757250ddb3bff1eecd7e41e65f7f833a8405fede0194319f87899690624f2122",
"sha256:7757ae33dae81c300487591c68790dfb5145c7d03324000433d9a2c141f82af7",
"sha256:7c6092102219f59ff29788860ccb021e80fffd953920c4a8653889c029b2d420",
"sha256:8122ba5f2a2169ca5da936b2e5a511740ffb73979381b4229d9188f6dcb22f1f",
"sha256:9c4a7ea4fb81536c1b1f5cc44d54a296f96ae78c1ebd2311bd0b60be45a48d96",
"sha256:c914f78da4953b33d4685e3cdc7ce63401247a21425c16a39760e282075ac4a6",
"sha256:cd401ccbc2a249a47a3a1724c2918fcd04be1f7b54eb2a5a71ff915db0ac51c6",
"sha256:d452a6746f0a7e11121e64625109bc4468fc3100452817001dbe018bb8b08514",
"sha256:ea6841bc3a76fa4942ce00f3bda7d436fda21e2d91602b9e21b7ca9ecab8f3ff",
"sha256:f8851ab9041756003119368c1e6cd0b9c631f46d686b3904b18c0139f4419f80"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.4.0"
},
"pyparsing": {
"hashes": [
"sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4",
"sha256:d9bdec0013ef1eb5a84ab39a3b3868911598afa494f5faa038647101504e2b81"
],
"markers": "python_version >= '3.6'",
"version": "==3.0.6"
},
"pyteal": {
"hashes": [
"sha256:6a7fbb2155ee79e0b6dfbd635e6ac4508a0c2279ddb4203f1c356b47bd684bb6",
"sha256:e395cf30fce630ac26157132ae4e0240845060a858a1a162aeac8b92a286b554"
],
"index": "pypi",
"version": "==0.9.1"
},
"pytest": {
"hashes": [
"sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89",
"sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"
],
"index": "pypi",
"version": "==6.2.5"
},
"six": {
"hashes": [
"sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
"sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.16.0"
},
"toml": {
"hashes": [
"sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
"sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"
],
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==0.10.2"
},
"tomli": {
"hashes": [
"sha256:b5bde28da1fed24b9bd1d4d2b8cba62300bfb4ec9a6187a957e8ddb9434c5224",
"sha256:c292c34f58502a1eb2bbb9f5bbc9a5ebc37bee10ffb8c2d6bbdfa8eb13cc14e1"
],
"markers": "python_version >= '3.7'",
"version": "==2.0.0"
},
"typing-extensions": {
"hashes": [
"sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e",
"sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"
],
"markers": "python_version >= '3.6'",
"version": "==4.0.1"
}
},
"develop": {}
}

248
third_party/algorand/setup.py vendored Normal file
View File

@ -0,0 +1,248 @@
from time import time, sleep
from typing import List, Tuple, Dict, Any, Optional, Union
from base64 import b64decode
import base64
import random
import hashlib
from algosdk.v2client.algod import AlgodClient
from algosdk.kmd import KMDClient
from algosdk import account, mnemonic
from algosdk.future import transaction
from algosdk.encoding import decode_address
from pyteal import compileTeal, Mode, Expr
from pyteal import *
from algosdk.logic import get_application_address
import pprint
# Q5XDfcbiqiBwfMlY3gO1Mb0vyNCO+szD3v9azhrG16iO5Z5aTduNzeut/FLG0NOG0+txrBGN6lhi5iwytgkyKg==
# position atom discover cluster fiction amused toe siren slam author surround spread garage craft isolate whisper kangaroo kitchen lend toss culture various effort absent kidney
class Account:
"""Represents a private key and address for an Algorand account"""
def __init__(self, privateKey: str) -> None:
self.sk = privateKey
self.addr = account.address_from_private_key(privateKey)
# print (privateKey + " -> " + self.getMnemonic())
def getAddress(self) -> str:
return self.addr
def getPrivateKey(self) -> str:
return self.sk
def getMnemonic(self) -> str:
return mnemonic.from_private_key(self.sk)
@classmethod
def FromMnemonic(cls, m: str) -> "Account":
return cls(mnemonic.to_private_key(m))
class PendingTxnResponse:
def __init__(self, response: Dict[str, Any]) -> None:
self.poolError: str = response["pool-error"]
self.txn: Dict[str, Any] = response["txn"]
self.applicationIndex: Optional[int] = response.get("application-index")
self.assetIndex: Optional[int] = response.get("asset-index")
self.closeRewards: Optional[int] = response.get("close-rewards")
self.closingAmount: Optional[int] = response.get("closing-amount")
self.confirmedRound: Optional[int] = response.get("confirmed-round")
self.globalStateDelta: Optional[Any] = response.get("global-state-delta")
self.localStateDelta: Optional[Any] = response.get("local-state-delta")
self.receiverRewards: Optional[int] = response.get("receiver-rewards")
self.senderRewards: Optional[int] = response.get("sender-rewards")
self.innerTxns: List[Any] = response.get("inner-txns", [])
self.logs: List[bytes] = [b64decode(l) for l in response.get("logs", [])]
class Setup:
def __init__(self) -> None:
self.ALGOD_ADDRESS = "http://localhost:4001"
self.ALGOD_TOKEN = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
self.FUNDING_AMOUNT = 100_000_000
self.KMD_ADDRESS = "http://localhost:4002"
self.KMD_TOKEN = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
self.KMD_WALLET_NAME = "unencrypted-default-wallet"
self.KMD_WALLET_PASSWORD = ""
self.TARGET_ACCOUNT = "position atom discover cluster fiction amused toe siren slam author surround spread garage craft isolate whisper kangaroo kitchen lend toss culture various effort absent kidney"
self.kmdAccounts : Optional[List[Account]] = None
self.accountList : List[Account] = []
self.APPROVAL_PROGRAM = b""
self.CLEAR_STATE_PROGRAM = b""
def waitForTransaction(
self, client: AlgodClient, txID: str, timeout: int = 10
) -> PendingTxnResponse:
lastStatus = client.status()
lastRound = lastStatus["last-round"]
startRound = lastRound
while lastRound < startRound + timeout:
pending_txn = client.pending_transaction_info(txID)
if pending_txn.get("confirmed-round", 0) > 0:
return PendingTxnResponse(pending_txn)
if pending_txn["pool-error"]:
raise Exception("Pool error: {}".format(pending_txn["pool-error"]))
lastStatus = client.status_after_block(lastRound + 1)
lastRound += 1
raise Exception(
"Transaction {} not confirmed after {} rounds".format(txID, timeout)
)
def getKmdClient(self) -> KMDClient:
return KMDClient(self.KMD_TOKEN, self.KMD_ADDRESS)
def getGenesisAccounts(self) -> List[Account]:
if self.kmdAccounts is None:
kmd = self.getKmdClient()
wallets = kmd.list_wallets()
walletID = None
for wallet in wallets:
if wallet["name"] == self.KMD_WALLET_NAME:
walletID = wallet["id"]
break
if walletID is None:
raise Exception("Wallet not found: {}".format(self.KMD_WALLET_NAME))
walletHandle = kmd.init_wallet_handle(walletID, self.KMD_WALLET_PASSWORD)
try:
addresses = kmd.list_keys(walletHandle)
privateKeys = [
kmd.export_key(walletHandle, self.KMD_WALLET_PASSWORD, addr)
for addr in addresses
]
self.kmdAccounts = [Account(sk) for sk in privateKeys]
finally:
kmd.release_wallet_handle(walletHandle)
return self.kmdAccounts
def getTargetAccount(self) -> Account:
return Account.FromMnemonic(self.TARGET_ACCOUNT)
def fundTargetAccount(self, client: AlgodClient, target: Account):
print("fundTargetAccount")
genesisAccounts = self.getGenesisAccounts()
suggestedParams = client.suggested_params()
for fundingAccount in genesisAccounts:
txn = transaction.PaymentTxn(
sender=fundingAccount.getAddress(),
receiver=target.getAddress(),
amt=self.FUNDING_AMOUNT,
sp=suggestedParams,
)
pprint.pprint(txn)
print("signing txn")
stxn = txn.sign(fundingAccount.getPrivateKey())
print("sending txn")
client.send_transaction(stxn)
print("waiting for txn")
self.waitForTransaction(client, stxn.get_txid())
def getAlgodClient(self) -> AlgodClient:
return AlgodClient(self.ALGOD_TOKEN, self.ALGOD_ADDRESS)
def getBalances(self, client: AlgodClient, account: str) -> Dict[int, int]:
balances: Dict[int, int] = dict()
accountInfo = client.account_info(account)
# set key 0 to Algo balance
balances[0] = accountInfo["amount"]
assets: List[Dict[str, Any]] = accountInfo.get("assets", [])
for assetHolding in assets:
assetID = assetHolding["asset-id"]
amount = assetHolding["amount"]
balances[assetID] = amount
return balances
def setup(self):
self.client = self.getAlgodClient()
self.target = self.getTargetAccount()
b = self.getBalances(self.client, self.target.getAddress())
if (b[0] < 100000000):
print("Account needs money... funding it")
self.fundTargetAccount(self.client, self.target)
print(self.getBalances(self.client, self.target.getAddress()))
def deploy(self):
vaa_processor_approval = self.client.compile(open("vaa-processor-approval.teal", "r").read())
vaa_processor_clear = self.client.compile(open("vaa-processor-clear.teal", "r").read())
vaa_verify = self.client.compile(open("vaa-verify.teal", "r").read())
verify_hash = vaa_verify['hash']
print("verify_hash " + verify_hash + " " + str(len(decode_address(verify_hash))))
globalSchema = transaction.StateSchema(num_uints=4, num_byte_slices=20)
localSchema = transaction.StateSchema(num_uints=0, num_byte_slices=0)
app_args = [ "beFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe", 0, 0 ]
txn = transaction.ApplicationCreateTxn(
sender=self.target.getAddress(),
on_complete=transaction.OnComplete.NoOpOC,
approval_program=b64decode(vaa_processor_approval["result"]),
clear_program=b64decode(vaa_processor_clear["result"]),
global_schema=globalSchema,
local_schema=localSchema,
app_args=app_args,
sp=self.client.suggested_params(),
)
signedTxn = txn.sign(self.target.getPrivateKey())
self.client.send_transaction(signedTxn)
response = self.waitForTransaction(self.client, signedTxn.get_txid())
assert response.applicationIndex is not None and response.applicationIndex > 0
print("app_id: ", response.applicationIndex)
appAddr = get_application_address(response.applicationIndex)
suggestedParams = self.client.suggested_params()
appCallTxn = transaction.ApplicationCallTxn(
sender=self.target.getAddress(),
index=response.applicationIndex,
on_complete=transaction.OnComplete.NoOpOC,
app_args=[b"setvphash", decode_address(verify_hash)],
sp=suggestedParams,
)
signedAppCallTxn = appCallTxn.sign(self.target.getPrivateKey())
self.client.send_transactions([signedAppCallTxn])
response = self.waitForTransaction(self.client, appCallTxn.get_txid())
print("set the vp hash to the stateless contract")
appCallTxn = transaction.PaymentTxn(
sender=self.target.getAddress(),
receiver=verify_hash,
amt=500000,
sp=suggestedParams,
)
signedAppCallTxn = appCallTxn.sign(self.target.getPrivateKey())
self.client.send_transactions([signedAppCallTxn])
response = self.waitForTransaction(self.client, appCallTxn.get_txid())
print("funded the stateless contract")
s = Setup()
s.setup()
s.deploy()

7
third_party/algorand/setup.sh vendored Executable file
View File

@ -0,0 +1,7 @@
#!/bin/bash
dn="$(dirname "$0")"
cd $dn
pipenv install
pipenv run python3 setup.py