Skip to content
This repository has been archived by the owner on Apr 8, 2024. It is now read-only.

Commit

Permalink
[PI-139]: Generate stark signature
Browse files Browse the repository at this point in the history
  • Loading branch information
arijoon committed Jul 25, 2023
1 parent 5b2f411 commit 16a5b0c
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 0 deletions.
73 changes: 73 additions & 0 deletions examples/33.generateL1RegistrationPayload.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/usr/bin/env -S yarn node
/* eslint-disable no-unused-vars */

/*
DO NOT EDIT THIS FILE BY HAND!
Examples are generated using helpers/buildExamples.js script.
Check README.md for more details.
*/

const sw = require('@rhino.fi/starkware-crypto')
const getWeb3 = require('./helpers/getWeb3')
const { utils } = require('web3')

const RhinofiClientFactory = require('../src')
const envVars = require('./helpers/loadFromEnvOrConfig')(
process.env.CONFIG_FILE_NAME
)
const logExampleResult = require('./helpers/logExampleResult')(__filename)

const ethPrivKey = envVars.ETH_PRIVATE_KEY
// NOTE: you can also generate a new key using:`
// const starkPrivKey = rhinofi.stark.createPrivateKey()
const starkPrivKey = envVars.STARK_PRIVATE_KEY
const rpcUrl = envVars.RPC_URL

const { web3, provider } = getWeb3(ethPrivKey, rpcUrl)

const rhinofiConfig = {
api: envVars.API_URL,
dataApi: envVars.DATA_API_URL,
useAuthHeader: true,
wallet: {
type: 'tradingKey',
meta: {
starkPrivateKey: starkPrivKey
}
}
// Add more variables to override default values
}

;(async () => {
const rhinofi = await RhinofiClientFactory(web3, rhinofiConfig)
const { starkKeyHex, ethAddress } = await rhinofi.getUserConfig()

console.log('Addresses', ethAddress, starkKeyHex)

const final = await rhinofi.stark.signRegistration(
starkPrivKey,
ethAddress
)

const starkExContract = new web3.eth.Contract(
rhinofi.contract.abi.getStarkEx(),
rhinofi.config.DVF.starkExContractAddress,
)

const callData = starkExContract.methods.registerEthAddress(
ethAddress,
starkKeyHex,
final
).encodeABI()

logExampleResult({
ethAddress,
starkKeyHex,
sig: final,
callData
})
})()
.catch(error => {
console.error(error)
process.exit(1)
})
5 changes: 5 additions & 0 deletions src/lib/dvf/bindApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ module.exports = () => {

// returns a function that will call api functions prepending dvf
// as first argument
/**
* @type {<T extends Function>(fn: T) => (...args: ParametersExceptFirst<T>) => ReturnType<T>}
*/
const compose = (funk, ...args) => {
return _partial(funk, dvf, ...args)
}
Expand All @@ -30,6 +33,8 @@ module.exports = () => {
}

dvf.stark = {
signRegistration: compose(require('../stark/signRegistration')),
createRegistrationMessage: compose(require('../stark/createRegistrationMessage')),
createOrder: compose(require('../stark/createOrder')),
createMarketOrder: compose(require('../stark/createMarketOrder')),
createOrderMessage: compose(require('../stark/createOrderMessage')),
Expand Down
5 changes: 5 additions & 0 deletions src/lib/dvf/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/**
* Simple typing file for manually adding types
*/

type ParametersExceptFirst<F> = F extends (head: any, ...tail: infer R) => any ? R : never
45 changes: 45 additions & 0 deletions src/lib/stark/createRegistrationMessage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const DVFError = require('../dvf/DVFError')
const sw = require('@rhino.fi/starkware-crypto')
const { utils } = require('web3')

// Constant from Starkware contract
// https://github.com/starkware-libs/starkex-contracts/blob/210bd5f6bcb6977211677821fe925140859a0f6e/scalable-dex/contracts/src/components/ECDSA.sol#L13-L14
const EC_ORDER = utils.BN('3618502788666131213697322783095070105526743751716087489154079457884512865583')

/**
* @type {(dvf: ReturnType<import('../dvf/bindApi')>,
* starkHex: string,
* ethAddress: string) => utils.BN}
*/
module.exports = (dvf, starkHex, ethAddress) => {
const starkware = dvf.sw || sw
if (!ethAddress) {
throw new Error('ethAddress is required')
}

if (!starkHex) {
throw new Error('ethAddress is required')
}

/*
uint256 msgHash = uint256(
keccak256(abi.encodePacked("UserRegistration:", ethKey, starkKey))
) % ECDSA.EC_ORDER;
*/

try {
const hashedMessage = utils.soliditySha3(
utils.encodePacked(
{ value: 'UserRegistration:', type: 'string' },
{ value: ethAddress, type: 'address' },
{ value: starkHex, type: 'uint256' },
)
)

const message = utils.BN(hashedMessage).mod(EC_ORDER).toString(16)

return message
} catch (error) {
throw new DVFError('ERR_CREATING_STARK_REGISTRATION_MESSAGE', { error })
}
}
39 changes: 39 additions & 0 deletions src/lib/stark/signRegistration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const DVFError = require('../dvf/DVFError')
const sw = require('@rhino.fi/starkware-crypto')

const pad = (rec) => rec.padStart(64, 0)

/**
* @type {(dvf: ReturnType<import('../dvf/bindApi')>,
* tradingKey: string,
* ethAddress: string) => string}
*/
module.exports = async (dvf, tradingKey, ethAddress) => {
const starkware = dvf.sw || sw
if (!tradingKey) {
throw new Error('tradingKey is required')
}

/*
uint256 msgHash = uint256(
keccak256(abi.encodePacked("UserRegistration:", ethKey, starkKey))
) % ECDSA.EC_ORDER;
*/

const { dvfStarkProvider } = dvf
const publicKey = await dvfStarkProvider.getPublicKey()

const message = dvf.stark.createRegistrationMessage(`0x${pad(publicKey.x)}`, ethAddress)

try {
const { starkKeyPair } = dvf.stark.createKeyPair(tradingKey)

const { r, s } = starkware.sign(starkKeyPair, message)

const final = `0x${pad(r.toString(16))}${pad(s.toString(16))}${pad(publicKey.y)}`

return final
} catch (error) {
throw new DVFError('ERR_CREATING_STARK_REGISTRATION_SIGNATURE', { error })
}
}

0 comments on commit 16a5b0c

Please sign in to comment.