Edit me

English / 한국어

스마트 컨트랙트의 설치 및 호출

Version 0.7.0

1. 계약설치

계약을 설치하려면 상응하는 트랜젝션을 생성하고 체인에 전송하여 실행해야 합니다.

계약을 구성하려면 계약내용의 16진수 문자열 및 설정 파라미터를 제공해야 합니다.

계약내용은 일반적으로 .avm문서(NEO버추얼머신과 호응) 및 .wasm문서(WASM버추얼머신과 호응)로 제공합니다.

설정 파라미터는 다음과 같습니다.

code계약내용은 16진수 문자열입니다.

vmType은 버추얼머신이며 현재 함수옵션은 다음과 같습니다.

export enum VmType {
    NativeVM = 0xFF,
    NEOVM    = 0x80,
    WASMVM   = 0x90
}

name은 일반 문자열로 된 계약 명칭이며 옵션값 입니다.

codeVersion은 일반 문자열로 된 계약 버전이며 옵션값 입니다.

author은 일반 문자열로 된 계약작성자이며 옵션값 입니다.

email은 일반 문자열로 된 계약작성자의 메일주소이며 옵션값 입니다.

desp는 일반 문자열로 된 계약서술이며 옵션값 입니다.

needStorage는 저장필요의 여부이며 불리언 및 옵션값 입니다.

import * as core from '../src/core'

//계약 내용 획득
var fs = require('fs')
var path = require('path')
let idContractAvm = fs.readFileSync(path.join(__dirname, '../src/smartcontract/data/IdContract.avm'))
var idContractAvmCode = ab2hexstring(idContractAvm)
var name = 'test',
	codeVersion = '1.0',
	author = 'alice',
	email = '',
	desp = '',
	needStorage = true;
//트랜젝션 구성	
var tx = core.makeDeployCodeTransaction(idContractAvmCode, VmType.NEOVm, name, codeVersion, author, email, desp, needStorage)
//트랜젝션 보내기
var param = buildRestfulParam(tx)
var url = TEST_ONT_URL.sendRawTxByRestful
axios.post(url, param).then((res:any)=> {
	console.log('deploy res: '+ JSON.stringify(res.data))
	//6초 후 설치 결과 조회.
    setTimeout(function () {
    	getContract(code, vmType)
    }, 6000)
    }).catch(err => {
   	   console.log('err: '+ err)
})

//체인에서의 계약 조회
const getContract = (avmCode, vmType=VmType.NEOVM) => {
    const codeHash = Address.fromVmCode(avmCode,vmType).serialize()
    let url = `${TEST_ONT_URL.REST_URL}/api/v1/contract/${codeHash}`
    console.log('url : '+ url)
    axios.get(url).then((res)=>{
        console.log(res.data)
    }).catch(err => {
        console.log(err)
    })
}

2. 계약호출

계약은 반드시 설치완료 후에 호출할 수 있습니다. 계약을 호출하려면 상응하는 트랜젝션을 생성하고 체인에 전송하여 실행해야 합니다.

2.1 abi문서를 통한 트랜젝션 구성

일반적인 스마트 컨트랙트은 상응하는 .avm문서와 .abi문서(NEO버추얼머신과 호응)로 컴파일될 수 있습니다. .abi 문서를 읽음으로써 스마트컨트랙트의 트랜잭션을 편리하게 구성 호출할 수 있습니다. .abi문서를 통해 편리하게 계약 트랜젝션을 호출할 수 있습니다. 구성된 트랜젝션은 유저 프라이빗서명이 필요할 수도 있습니다.

TS SDK에서 Abi와 관련된 클래스는 AbiInfo, AbiFunction, Parameter등이 있습니다.

class AbiInfo {
    hash : string
    entrypoint : string
    functions : Array<AbiFunction>
}

hash는 스마트 컨트랙트의 hash함수입니다. 계약주소라고도 불리며 각각의 계약을 구분하는데 사용합니다.

entrypoint은 계약의 엔터함수명입니다.

functions은 계약이 제공하는 함수집합입니다.

class AbiFunction {
    name : string
    returntype : string
    parameters : Array<Parameter>
}

name은 함수명칭입니다.

returntype은 함수리턴값값 유형입니다.

parameters는 함수 파라미터 리스트입니다.

class Parameter {
    name : string
    type : ParameterType
    value : any
}

name은 파라미터 명칭입니다.

type는 파라미터 유형입니다.

value는 파라미터값 입니다.

계약abi파일을 읽고 해당 객체를 생성하면 트랜잭션을 빌드하는데 필요한 함수이름, 파라미터 및 계약 해시를 제공하는 것이 편리합니다.

트랜잭션을 빌드하는 함수에 필요한 파라미터는 아래와 같습니다.

function makeInvokeTransaction(funcName : string, parameters : Array<Parameter>, contractHash : string, vmType : VmType = VmType.NEOVM, fees : Array<Fee> = [])

funcName은 호출한 계약의 함수명칭입니다.

parameters는 함수의 파라미터 대상 리스트입니다.

contractHash는 계약 hash입니다.

vmType는 버추얼머신 유형입니다.

fees는 트랜젝션 전송 비용입니다.

다음은 ONT ID스마트 컨트랙트에서 ONT ID를 등록하는 방식을 예시로 전체 과정을 설명한 내용입니다.

//abi문서 읽기. 이 문서는 JSON을 불러옵니다.
import abiJson from '../smartcontract/data/idContract.abi'
//abi내용 해석
const abiInfo = AbiInfo.parseJson(JSON.stringify(abiJson))

//AbiFunction읽기

const abiInfo = AbiInfo.parseJson(JSON.stringify(abiJson))

//AbiFunction읽기
const abiFunction = abiInfo.getFunction('RegIdWithPublicKey')

const privateKey = '7c47df9664e7db85c1308c080f398400cb24283f5d922e76b478b5429e821b95'
const publicKey = '1202037fa2bbad721197da4f2882e4f8e4ef6a77dbc7cfbd72267cdd72dd60ac30b41e'
const ontid = '6469643a6f6e743a544d7876617353794747486e7574674d67657158443556713265706b6a476f737951'

//파라미터 구성. 이 파라미터 유형은 16진수 문자열인 ByteArray입니다.
let p1 = new Parameter(f.parameters[0].getName(), ParameterType.ByteArray, ontid)
let p2 = new Parameter(f.parameters[1].getName(), ParameterType.ByteArray, publicKey)

//파라미터 설정
abiFunction.setParasValue(p1, p2)

//트랜젝션 대상 구성
let fees = []
let vmType = VmType.NEOVM
let tx = makeInvokeTransaction(abiFunction.name, abiFunction.parameters, abiInfo.hash, vmType, fees)

//트랜젝션 서명. 현재 최종적으로 구성된 트랜젝션을 얻을 수 있습니다. 
signTransaction(tx, privateKey)

2.2 WASM기반 계약의 트랜잭션 구성

WASM기반 버추얼머신의 스마트컨트랙트는 계약 컴파일러에 abi문서가 생성되지 않습니다. 하지만 정확한 함수명과 파라미터 대상에 대해 동일한 방법으로 트랜젝션을 구성할 수 있습니다.

const codeHash = '9007be541a1aef3d566aa219a74ef16e71644715'
const params = [
		new Parameter('p1', ParameterType.Int, 20), 
		new Parameter('p2', ParameterType.Int, 30)
	]
const funcName = 'add'
let tx = makeInvokeTransaction(funcName, params, codeHash, VmType.WASMVM)

2.3 트랜젝션 전송

다양한 방식으로 트랜젝션을 체인에 전송하여 실행할 수 있습니다.

2.3.1 Restful

//팩킹대상을 이용하여 요청 전송
let restClient = new RestClient()
//사용 이전에 트랜젝션 대상을 이용하여 요청 파라미터 생성 
restClient.sendRawTransaction(tx.serialize()).then(res => {
    console.log(res)
})

요청은 해당 트랜젝션hash를 리턴하고 트랜젝션hash를 통해 계약의 실행결과를 조회해야 합니다. 비교적 간단한 방법은 온톨지의 블록체인 브라우저에서 조회하는 것입니다.

2.3.2 Rpc

let rpcClient = new RpcClient()
rpcClient.sendRawTransaction(tx.serialize()).then(res => {
    console.log(res)
})

Rpc요청과 Restful은 유사하며 리턴결과는 모두 트랜젝션 hash입니다.

2.3.3 Websocket

Websocket을 통해 요청을 전송하면 백그라운드에서 푸시한 정보를 모니터링 할 수 있습니다. 만약 계약에 시나리오 푸시가 명시되어 있으면 계약방식 호출 후 상응하는 푸시 정보가 나타납니다.

//요청 파라미터 구성
let param = buildTxParam(tx)
let txSender = new TxSender(TEST_ONT_URL.SOCKET_URL)
//콜백 파라미터 정의
//@param err 결과오류 
//@param res 모니터링한 정보
//@param socket websocket대상
const callback = (err, res, socket) => {
    if(err) {
        console.log(err)
        socket.close()
        return;
    }
    if(res.Action === 'Notify') {
        console.log('Notify: '+ JSON.stringify(res))
        socket.close()
    }
}
txSender.sendTxWithSocket(param, callback)