Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"commitmsg": "kleros-scripts commitmsg",
"cz": "kleros-scripts cz",
"invoke": "env-cmd ./.env serverless invoke -l -f",
"build": "docker run --rm -v $PWD:/data -w /data lambci/lambda:build-nodejs8.10 npm rebuild scrypt",
"build": "docker run --rm -v $PWD:/data -w /data node:8 npm rebuild scrypt",
"deploy:function": "env-cmd ./.env serverless deploy function -f",
"deploy:staging": "env-cmd ./.env serverless deploy",
"deploy": "env-cmd ./.env serverless deploy -s production"
Expand Down
14 changes: 2 additions & 12 deletions serverless.yml
Original file line number Diff line number Diff line change
Expand Up @@ -251,12 +251,7 @@ functions:
- {
Effect: Allow,
Action: ['dynamodb:Query'],
Resource: 'arn:aws:dynamodb:us-east-2:547511976516:table/kovan-justifications',
}
- {
Effect: Allow,
Action: ['dynamodb:Query'],
Resource: 'arn:aws:dynamodb:us-east-2:547511976516:table/mainnet-justifications',
Resource: 'arn:aws:dynamodb:us-east-2:547511976516:table/justifications',
}
documentation:
summary: 'Get justifications for a dispute round.'
Expand Down Expand Up @@ -295,12 +290,7 @@ functions:
- {
Effect: Allow,
Action: ['dynamodb:PutItem'],
Resource: 'arn:aws:dynamodb:us-east-2:547511976516:table/kovan-justifications',
}
- {
Effect: Allow,
Action: ['dynamodb:PutItem'],
Resource: 'arn:aws:dynamodb:us-east-2:547511976516:table/mainnet-justifications',
Resource: 'arn:aws:dynamodb:us-east-2:547511976516:table/justifications',
}
documentation:
summary: 'Put justification for a vote.'
Expand Down
90 changes: 49 additions & 41 deletions src/court/justifications.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ module.exports.get = async (event, _context, callback) => {
}
},
KeyConditionExpression: 'disputeIDAndAppeal = :disputeIDAndAppeal',
TableName: `${payload.network}-justifications`
TableName: 'justifications'
})
}
})
Expand All @@ -32,63 +32,71 @@ module.exports.put = async (event, _context, callback) => {
process.env.KLEROS_LIQUID_ADDRESS
)

// Validate signature
const payload = JSON.parse(event.body).payload

// Verify votes belong to user
const dispute = await klerosLiquid.methods.getDispute(
payload.justification.disputeID
).call()

// Get number of votes in current round
const votesInRound = dispute.votesLengths[payload.justification.appeal]

let drawn = false
let voteID
for (let i = 0; i < Number(votesInRound); i++) {
const vote = await klerosLiquid.methods
.getVote(payload.justification.disputeID, payload.justification.appeal, i)
.call()
if (vote.account === payload.address) {
// If voted, can no longer submit justification.
if (vote.voted) {
return callback(null, {
statusCode: 403,
headers: { 'Access-Control-Allow-Origin': '*' },
body: JSON.stringify({
error: 'This address has already cast their vote.'
})
})
}
// Once we know address has been drawn we can stop searching.
drawn = true
voteID = i
break
}
}

if (!drawn) {
try {
if (
(await web3.eth.accounts.recover(
JSON.stringify(payload.justification),
payload.signature
)) !==
(await dynamoDB.getItem({
Key: { address: { S: payload.address } },
TableName: 'user-settings',
ProjectionExpression: 'derivedAccountAddress'
})).Item.derivedAccountAddress.S
)
throw new Error(
"Signature does not match the supplied address' derived account address for justifications."
)
} catch (err) {
console.error(err)
return callback(null, {
statusCode: 403,
headers: { 'Access-Control-Allow-Origin': '*' },
body: JSON.stringify({
error: 'This address was not drawn.'
error:
"Signature is invalid or does not match the supplied address' derived account address for justifications."
})
})
}

// Save justification.
// Verify votes belong to user
for (const voteID of payload.justification.voteIDs) {
const vote = await klerosLiquid.methods
.getVote(
payload.justification.disputeID,
payload.justification.appeal,
voteID
)
.call()
if (vote.account !== payload.address || vote.voted)
return callback(null, {
statusCode: 403,
headers: { 'Access-Control-Allow-Origin': '*' },
body: JSON.stringify({
error:
'Not all of the supplied vote IDs belong to the supplied address and are not cast.'
})
})
}

// Save justification
await dynamoDB.putItem({
Item: {
disputeIDAndAppeal: {
S: `${payload.justification.disputeID}-${payload.justification.appeal}`
},
address: {
S: payload.address
voteID: {
N: String(
payload.justification.voteIDs[
payload.justification.voteIDs.length - 1
]
)
},
voteID: { N: String(voteID) },
justification: { S: payload.justification.justification }
},
TableName: `${payload.network}-justifications`
TableName: 'justifications'
})
callback(null, {
statusCode: 200,
Expand Down
21 changes: 9 additions & 12 deletions src/global/user-settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,16 @@ module.exports.get = async (event, _context, callback) => {
// Validate signature
const payload = JSON.parse(event.body).payload
try {
const account = await web3.eth.accounts.recover(
JSON.stringify(payload.settings),
payload.signature
)
// accept if sig is from account or derived account
if (
account !== payload.address &&
account !==
(await dynamoDB.getItem({
Key: { address: { S: payload.address } },
TableName: 'user-settings',
ProjectionExpression: 'derivedAccountAddress'
})).Item.derivedAccountAddress.S
(await web3.eth.accounts.recover(
JSON.stringify(payload.settings),
payload.signature
)) !==
(await dynamoDB.getItem({
Key: { address: { S: payload.address } },
TableName: 'user-settings',
ProjectionExpression: 'derivedAccountAddress'
})).Item.derivedAccountAddress.S
)
throw new Error('Signature does not match supplied address.')
} catch (err) {
Expand Down