Terra contract deployment moved to a separate k8s job (#130)

* Terra contract deployment moved to a separate k8s job

* terra-contracts job moved to the terrad stateful set as a sidecar, terra test addresses added to DEVELOP.md
This commit is contained in:
Yuriy Savchenko 2020-12-03 15:37:23 +02:00 committed by GitHub
parent d1f572c70f
commit e8b411107d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 173 additions and 68 deletions

View File

@ -127,3 +127,11 @@ using `kubectl exec solana-devnet-0 -c setup cli airdrop solana-devnet:9900` (se
| `0xe78A0F7E598Cc8b0Bb87894B0F60dD2a88d6a8Ab` | Wrapped asset contract |
| `0xCfEB869F69431e42cdB54A4F4f105C19C080A601` | Example ERC20 token |
| `0xf5b1d8fab1054b9cf7db274126972f97f9d42a11` | Wrapped asset address for the 6qRhs8oA... SPL token |
**Terra**
| Account | Description |
|------------------------------------------------|-----------------------------------------------------|
| `terra1x46rqay4d3cssq8gxxvqz8xt6nwlz4td20k38v` | Main test account |
| `terra18vd8fpwxzck93qlwghaj6arh4p7c5n896xzem5` | Test token account to send via bridge |
| `terra174kgn5rtw4kf6f938wm7kwh70h2v4vcfd26jlc` | Bridge contract instance |

View File

@ -154,8 +154,14 @@ k8s_resource("web", port_forwards=[
docker_build(
ref = "terra-image",
context = "./terra/docker",
dockerfile = "terra/docker/Dockerfile",
context = "./terra/devnet",
dockerfile = "terra/devnet/Dockerfile",
)
docker_build(
ref = "terra-contracts",
context = "./terra",
dockerfile = "./terra/Dockerfile",
)
k8s_yaml("devnet/terra-devnet.yaml")

View File

@ -89,5 +89,7 @@ spec:
httpGet:
port: 26657
resources: {}
- name: terra-contracts
image: terra-contracts
restartPolicy: Always
serviceName: terra-terrad

3
terra/.dockerignore Normal file
View File

@ -0,0 +1,3 @@
target
tools/node_modules
tools/dist

26
terra/Dockerfile Normal file
View File

@ -0,0 +1,26 @@
# This is a multi-stage docker file, first stage builds contracts
# And the second one creates node.js environment to deploy them
FROM cosmwasm/workspace-optimizer:0.10.4 AS builder
ADD Cargo.lock /code/
ADD Cargo.toml /code/
ADD contracts /code/contracts
RUN optimize_workspace.sh
# Contract deployment stage
FROM node:14
RUN npm update && npm i -g typescript ts-node
WORKDIR /app/tools
COPY --from=builder /code/artifacts /app/artifacts
ADD ./artifacts/cw20_base.wasm /app/artifacts/
ADD ./tools /app/tools
RUN chmod +x /app/tools/deploy.sh
RUN npm install
RUN ts-node --version
ENTRYPOINT /app/tools/deploy.sh

View File

@ -2,8 +2,14 @@
docker_build(
ref = "terra-image",
context = "./docker",
dockerfile = "./docker/Dockerfile",
context = "./devnet",
dockerfile = "./devnet/Dockerfile",
)
docker_build(
ref = "terra-contracts",
context = ".",
dockerfile = "./Dockerfile",
)
k8s_yaml("../devnet/terra-devnet.yaml")

View File

@ -1,29 +0,0 @@
# Wormhole + Terra local test environment
For the list of dependencies please follow [DEVELOP.md](../../DEVELOP.md).
Additional dependencies:
- [Node.js](https://nodejs.org/) >= 14.x, [ts-node](https://www.npmjs.com/package/ts-node) >= 8.x
Start Tilt from the project root:
tilt up --update-mode=exec -- --num=1
Afterwards use test scripts in `terra/tools` folder:
npm install
npm run prepare-token
npm run prepare-wormhole
These commands will give you two important addresses: test token address and Wormhole contract address on Terra.
Now you need to change guardian configuration to monitor the right contract. Copy Wormhole contract address and
replace existing `TERRA_FEE_PAYER` address in `devnet/bridge.yaml`.
Save the changes and monitor Tilt dashboard until guardian services restart.
Now use both token address and Wormhole contract address to issue tocken lock transaction:
npm run lock-tocken -- TOKEN_CONTRACT WORMHOLE_CONTRACT 1000
Where 1000 is a sample amount to transfer. After this command is issued monitor Guardian service in Tilt dashboard
to see its effects propagated to the destination blockchain (in this case it is Ethereum).

5
terra/tools/deploy.sh Normal file
View File

@ -0,0 +1,5 @@
npm run prepare-token http://terra-lcd:1317
npm run prepare-wormhole http://terra-lcd:1317
npm run lock-token terra18vd8fpwxzck93qlwghaj6arh4p7c5n896xzem5 terra174kgn5rtw4kf6f938wm7kwh70h2v4vcfd26jlc 1000 http://terra-lcd:1317
echo "Going to sleep, interrupt if running manually"
sleep infinity

View File

@ -1,4 +1,4 @@
import { execute_contract, query_contract } from './utils';
import { init_lcd, execute_contract, query_contract } from './utils';
async function script() {
if (process.argv.length < 5) {
@ -22,4 +22,5 @@ async function script() {
console.log('Tokens locked');
}
init_lcd(process.argv[5]);
script();

View File

@ -27,6 +27,11 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.6.tgz",
"integrity": "sha512-6QlRuqsQ/Ox/aJEQWBEJG7A9+u7oSYl3mem/K8IzxXG/kAGbV1YPD9Bg9Zw3vyxC/YP+zONKwy8hGkSt1jxFMw=="
},
"arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="
},
"axios": {
"version": "0.20.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.20.0.tgz",
@ -123,6 +128,11 @@
"safe-buffer": "^5.1.2"
}
},
"buffer-from": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
},
"bufferutil": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.2.tgz",
@ -180,6 +190,11 @@
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.2.1.tgz",
"integrity": "sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw=="
},
"diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A=="
},
"elliptic": {
"version": "6.5.3",
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz",
@ -243,6 +258,11 @@
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="
},
"md5.js": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
@ -383,6 +403,20 @@
"safe-buffer": "^5.0.1"
}
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
},
"source-map-support": {
"version": "0.5.19",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
"integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
"requires": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
}
},
"string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
@ -403,11 +437,28 @@
"nan": "^2.13.2"
}
},
"ts-node": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.0.0.tgz",
"integrity": "sha512-/TqB4SnererCDR/vb4S/QvSZvzQMJN8daAslg7MeaiHvD8rDZsSfXmNeNumyZZzMned72Xoq/isQljYSt8Ynfg==",
"requires": {
"arg": "^4.1.0",
"diff": "^4.0.1",
"make-error": "^1.1.1",
"source-map-support": "^0.5.17",
"yn": "3.1.1"
}
},
"typeforce": {
"version": "1.18.0",
"resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz",
"integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g=="
},
"typescript": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.2.tgz",
"integrity": "sha512-thGloWsGH3SOxv1SoY7QojKi0tc+8FnOmiarEGMbd/lar7QOEd3hvlx3Fp5y6FlDUGl9L+pd4n2e+oToGMmhRQ=="
},
"utf-8-validate": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.3.tgz",
@ -433,6 +484,11 @@
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz",
"integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA=="
},
"yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q=="
}
}
}

View File

@ -1,7 +1,8 @@
{
"name": "terra-contract-tools",
"version": "1.0.0",
"description": "",
"description": "Tools to build and deploy Terra contracts",
"repository": "https://github.com/certusone/wormhole",
"main": "index.js",
"scripts": {
"build-contracts": "( cd .. && docker run --rm -v \"$(pwd)\":/code --mount type=volume,source=\"$(basename \"$(pwd)\")_cache\",target=/code/target --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry cosmwasm/workspace-optimizer:0.10.4 )",
@ -12,9 +13,10 @@
},
"author": "",
"license": "ISC",
"type": "module",
"dependencies": {
"@terra-money/terra.js": "^0.5.12",
"@types/node": "^14.14.6"
"@types/node": "^14.14.6",
"ts-node": "^9.0.0",
"typescript": "^4.1.2"
}
}

View File

@ -1,4 +1,4 @@
import { deploy_contract, instantiate_contract, query_contract } from './utils';
import { init_lcd, deploy_contract, instantiate_contract, query_contract } from './utils';
async function script() {
const TEST_ADDRESS: string = 'terra1x46rqay4d3cssq8gxxvqz8xt6nwlz4td20k38v';
@ -24,4 +24,5 @@ async function script() {
console.log(`${TEST_ADDRESS} balance is ${result.balance}`);
}
init_lcd(process.argv[2]);
script();

View File

@ -1,4 +1,4 @@
import { deploy_contract, instantiate_contract, query_contract } from './utils';
import { init_lcd, deploy_contract, instantiate_contract, query_contract } from './utils';
async function script() {
// Deploy cw20-wrapped
@ -23,4 +23,5 @@ async function script() {
console.log(`Wormhole instance created at ${contract_address}`);
}
init_lcd(process.argv[2]);
script();

View File

@ -1,4 +1,4 @@
import { execute_contract } from './utils';
import { init_lcd, execute_contract } from './utils';
async function script() {
if (process.argv.length < 3) {
@ -14,4 +14,5 @@ async function script() {
console.log('Vaa submitted');
}
init_lcd(process.argv[3]);
script();

View File

@ -6,12 +6,21 @@ const mk = new MnemonicKey({
mnemonic: 'notice oak worry limit wrap speak medal online prefer cluster roof addict wrist behave treat actual wasp year salad speed social layer crew genius'
})
// connect to localterra
const terra = new LCDClient({
URL: 'http://localhost:1317',
chainID: 'localterra'
});
const wallet = terra.wallet(mk);
let terra: LCDClient;
let wallet;
export function init_lcd(host_name='http://localhost:1317') {
// connect to localterra
terra = new LCDClient({
URL: host_name,
chainID: 'localterra'
});
wallet = terra.wallet(mk);
}
function delay(ms: number) {
return new Promise( resolve => setTimeout(resolve, ms) );
}
export async function deploy_contract(wasm_file) : Promise<number> {
@ -19,31 +28,38 @@ export async function deploy_contract(wasm_file) : Promise<number> {
wallet.key.accAddress,
fs.readFileSync(wasm_file).toString('base64')
);
try {
const storeCodeTx = await wallet.createAndSignTx({
msgs: [storeCode],
});
const storeCodeTxResult = await terra.tx.broadcast(storeCodeTx);
let first_attempt = true;
for (;;) {
try {
const storeCodeTx = await wallet.createAndSignTx({
msgs: [storeCode],
});
const storeCodeTxResult = await terra.tx.broadcast(storeCodeTx);
//console.log(storeCodeTxResult);
//console.log(storeCodeTxResult);
if (isTxError(storeCodeTxResult)) {
throw new Error(
`store code failed. code: ${storeCodeTxResult.code}, codespace: ${storeCodeTxResult.codespace}, raw_log: ${storeCodeTxResult.raw_log}`
);
if (isTxError(storeCodeTxResult)) {
throw new Error(
`store code failed. code: ${storeCodeTxResult.code}, codespace: ${storeCodeTxResult.codespace}, raw_log: ${storeCodeTxResult.raw_log}`
);
}
const {
store_code: { code_id },
} = storeCodeTxResult.logs[0].eventsByType;
return parseInt(code_id[0], 10);
} catch (err) {
// Only show error from the second time it shows to avoid spamming errors while initialization not yet finished
if (!first_attempt) {
console.log(`Error ${err}`);
if (err.response) {
console.log(err.response.data);
}
}
first_attempt = false;
await delay(5000);
}
const {
store_code: { code_id },
} = storeCodeTxResult.logs[0].eventsByType;
return parseInt(code_id[0], 10);
} catch (err) {
console.log(`Error ${err}`);
if (err.response) {
console.log(err.response.data);
}
return -1;
}
}