Skip to content

Commit

Permalink
Merge pull request #332 from StakerDAO/open-oven
Browse files Browse the repository at this point in the history
Add Functionality to Open an Oven
  • Loading branch information
anonymoussprocket committed Nov 25, 2020
2 parents 87eee48 + 3bedc15 commit 6e1caba
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 11 deletions.
44 changes: 44 additions & 0 deletions src/chain/tezos/TezosMessageUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -552,4 +552,48 @@ export namespace TezosMessageUtils {

return n.toJSNumber();
}

/**
* Calculate the address of a contract that was originated.
*
* @param operationHash The operation group hash.
* @param index The index of the origination operation in the operation group.
*/
export function calculateContractAddress(operationHash: string, index: number): string {
// Decode and slice two byte prefix off operation hash.
const decoded: Uint8Array = base58check.decode(operationHash).slice(2)

// Merge the decoded buffer with the operation prefix.
let decodedAndOperationPrefix: Array<number> = []
for (let i = 0; i < decoded.length; i++) {
decodedAndOperationPrefix.push(decoded[i])
}
decodedAndOperationPrefix = decodedAndOperationPrefix.concat([
(index & 0xff000000) >> 24,
(index & 0x00ff0000) >> 16,
(index & 0x0000ff00) >> 8,
index & 0x000000ff,
])

// Hash and encode.
const hash = blakejs.blake2b(new Uint8Array(decodedAndOperationPrefix), null, 20)
const smartContractAddressPrefix = new Uint8Array([2, 90, 121]) // KT1
const prefixedBytes = mergeBytes(smartContractAddressPrefix, hash)
return base58check.encode(prefixedBytes)
}

/**
* Helper to merge two Uint8Arrays.
*
* @param a The first array.
* @param b The second array.
* @returns A new array that contains b appended to the end of a.
*/
function mergeBytes(a: Uint8Array, b: Uint8Array): Uint8Array {
const merged = new Uint8Array(a.length + b.length)
merged.set(a)
merged.set(b, a.length)

return merged
}
}
86 changes: 75 additions & 11 deletions src/chain/tezos/contracts/WrappedTezosHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import { TezosMessageUtils } from '../TezosMessageUtil';
import { TezosNodeReader } from '../TezosNodeReader';
import { TezosNodeWriter } from '../TezosNodeWriter';
import { TezosContractUtils } from './TezosContractUtils';
import { TezosParameterFormat } from '../../../types/tezos/TezosChainTypes';

/** The expected checksum for the Wrapped Tezos contracts. */
const CONTRACT_CHECKSUMS = {
token: 'd48b45bd77d2300026fe617c5ba7670e',
oven: '5e3c30607da21a0fc30f7be61afb15c7'

// TODO(keefertaylor): Implement additional checksums for core contract here.
oven: '5e3c30607da21a0fc30f7be61afb15c7',
core: '7b9b5b7e7f0283ff6388eb783e23c452'
}

/** The expected checksum for the Wrapped Tezos scripts. */
Expand All @@ -21,8 +21,19 @@ const SCRIPT_CHECKSUMS = {
token: '',
// TODO(keefertaylor): Compute this checksum correctly.
oven: '',
// TODO(keefertaylor): Compute this checksum correctly.
core: ''
}

/**
* Property bag containing the results of opening an oven.
*/
export type OpenOvenResult = {
// The operation hash of the request to open an oven.
operationHash: string

// TODO(keefertaylor): Implement additional checksums for core script here.
// The address of the new oven contract.
ovenAddress: string
}

export interface WrappedTezosStorage {
Expand Down Expand Up @@ -67,18 +78,20 @@ export namespace WrappedTezosHelper {
* @param nodeUrl The URL of the Tezos node which serves data.
* @param tokenContractAddress The address of the token contract.
* @param ovenContractAddress The address of an oven contract.
* @param coreContractAddress The address of the core contract.
* @returns A boolean indicating if the code was the expected sum.
*/
export async function verifyDestination(
nodeUrl: string,
tokenContractAddress: string,
ovenContractAddress: string
ovenContractAddress: string,
coreContractAddress: string
): Promise<boolean> {
// TODO(keefertaylor): Verify checksums for core contract here.
const tokenMatched = TezosContractUtils.verifyDestination(nodeUrl, tokenContractAddress, CONTRACT_CHECKSUMS.token)
const ovenMatched = TezosContractUtils.verifyDestination(nodeUrl, ovenContractAddress, CONTRACT_CHECKSUMS.oven)
const coreMatched = TezosContractUtils.verifyDestination(nodeUrl, coreContractAddress, CONTRACT_CHECKSUMS.core)

return tokenMatched && ovenMatched
return tokenMatched && ovenMatched && coreMatched
}

/**
Expand All @@ -88,15 +101,16 @@ export namespace WrappedTezosHelper {
*
* @param tokenScript The script of the token contract.
* @param ovenScript The script of an oven contract.
* @param coreScript The script of the core contract.
* @returns A boolean indicating if the code was the expected sum.
*/

export function verifyScript(tokenScript: string): boolean {
// TODO(keefertaylor): Verify checksums for core script here.
export function verifyScript(tokenScript: string, ovenScript, string, coreScript: string): boolean {
const tokenMatched = TezosContractUtils.verifyScript(tokenScript, SCRIPT_CHECKSUMS.token)
const ovenMatched = TezosContractUtils.verifyScript(tokenScript, SCRIPT_CHECKSUMS.oven)
const ovenMatched = TezosContractUtils.verifyScript(ovenScript, SCRIPT_CHECKSUMS.oven)
const coreMatched = TezosContractUtils.verifyScript(coreScript, SCRIPT_CHECKSUMS.core)

return tokenMatched && ovenMatched
return tokenMatched && ovenMatched && coreMatched
}

/**
Expand Down Expand Up @@ -275,4 +289,54 @@ export namespace WrappedTezosHelper {

return TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID);
}

/**
* Open a new oven.
*
* The oven's owner is assigned to the sender's address.
*
* @param nodeUrl The URL of the Tezos node which serves data.
* @param signer A Signer for the sourceAddress.
* @param keystore A Keystore for the sourceAddress.
* @param fee The fee to use.
* @param coreAddress The address of the core contract.
* @param gasLimit The gas limit to use.
* @param storageLimit The storage limit to use.
* @returns A property bag of data about the operation.
*/
export async function openOven(
nodeUrl: string,
signer: Signer,
keystore: KeyStore,
fee: number,
coreAddress: string,
gasLimit: number,
storageLimit: number
): Promise<OpenOvenResult> {
const entryPoint = 'runEntrypointLambda'
const lambdaName = 'createOven'
const bytes = TezosMessageUtils.writePackedData(`Pair None "${keystore.publicKeyHash}"`, 'pair (option key_hash) address', TezosParameterFormat.Michelson)
const parameters = `Pair "${lambdaName}" 0x${bytes}`

const nodeResult = await TezosNodeWriter.sendContractInvocationOperation(
nodeUrl,
signer,
keystore,
coreAddress,
0,
fee,
storageLimit,
gasLimit,
entryPoint,
parameters,
TezosTypes.TezosParameterFormat.Michelson
)

const operationHash = TezosContractUtils.clearRPCOperationGroupHash(nodeResult.operationGroupID);
const ovenAddress = TezosMessageUtils.calculateContractAddress(operationHash, 0)
return {
operationHash,
ovenAddress
}
}
}

0 comments on commit 6e1caba

Please sign in to comment.