Skip to content

Commit 6e083bc

Browse files
committed
Check that a transcoder is registered when submitting a transcode claim
1 parent 48de5b4 commit 6e083bc

File tree

5 files changed

+20
-57
lines changed

5 files changed

+20
-57
lines changed

Diff for: contracts/bonding/BondingManager.sol

+8
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,14 @@ contract BondingManager is ManagerProxyTarget, IBondingManager {
796796
return activeTranscoderSet[_round].isActive[_transcoder];
797797
}
798798

799+
/*
800+
* @dev Return whether a transcoder is registered
801+
* @param _transcoder Transcoder address
802+
*/
803+
function isRegisteredTranscoder(address _transcoder) public view returns (bool) {
804+
return transcoderStatus(_transcoder) == TranscoderStatus.Registered;
805+
}
806+
799807
/*
800808
* @dev Remove transcoder
801809
*/

Diff for: contracts/bonding/IBondingManager.sol

+1
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,6 @@ contract IBondingManager {
2525
// Public functions
2626
function transcoderTotalStake(address _transcoder) public view returns (uint256);
2727
function activeTranscoderTotalStake(address _transcoder, uint256 _round) public view returns (uint256);
28+
function isRegisteredTranscoder(address _transcoder) public view returns (bool);
2829
function getTotalBonded() public view returns (uint256);
2930
}

Diff for: contracts/jobs/JobsManager.sol

+2
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,8 @@ contract JobsManager is ManagerProxyTarget, IVerifiable, IJobsManager {
319319
require(jobStatus(_jobId) != JobStatus.Inactive);
320320
// Segment range must be valid
321321
require(_segmentRange[1] >= _segmentRange[0]);
322+
// Caller must be registered transcoder
323+
require(bondingManager().isRegisteredTranscoder(msg.sender));
322324

323325
uint256 blockNum = roundsManager().blockNum();
324326

Diff for: contracts/test/BondingManagerMock.sol

+4
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,8 @@ contract BondingManagerMock is IBondingManager {
7373
function activeTranscoderTotalStake(address _transcoder, uint256 _round) public view returns (uint256) {
7474
return activeStake;
7575
}
76+
77+
function isRegisteredTranscoder(address _transcoder) public view returns (bool) {
78+
return true;
79+
}
7680
}

Diff for: test/integration/SlashingEdgeCases.js

+5-57
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import batchTranscodeReceiptHashes from "../../utils/batchTranscodeReceipts"
33
import MerkleTree from "../../utils/merkleTree"
44
import {createTranscodingOptions} from "../../utils/videoProfile"
55
import Segment from "../../utils/segment"
6+
import expectThrow from "../helpers/expectThrow"
67

78
const Controller = artifacts.require("Controller")
89
const BondingManager = artifacts.require("BondingManager")
@@ -157,7 +158,7 @@ contract("SlashingEdgeCases", accounts => {
157158
assert.equal(await bondingManager.getTotalBonded(), expTotalBondedRemaining, "wrong total bonded amount")
158159
})
159160

160-
it("transcoder that is slashed should still be slashable if it claims work and faults again", async () => {
161+
it("transcoder that is slashed should not be able to claims work", async () => {
161162
await token.approve(bondingManager.address, 1000, {from: transcoder2})
162163
await bondingManager.bond(1000, transcoder2, {from: transcoder2})
163164
await bondingManager.transcoder(10, 15, 1, {from: transcoder2})
@@ -198,9 +199,6 @@ contract("SlashingEdgeCases", accounts => {
198199
// Build merkle tree
199200
const merkleTree = new MerkleTree(tReceiptHashes)
200201

201-
const tokenStartSupply = await token.totalSupply.call()
202-
const watcherStartBalance = await token.balanceOf(watcher)
203-
204202
// Transcoder claims segments 0 through 3
205203
await jobsManager.claimWork(1, [0, 3], merkleTree.getHexRoot(), {from: transcoder2})
206204
// Transcoder claims segments 0 through 3 again
@@ -212,58 +210,8 @@ contract("SlashingEdgeCases", accounts => {
212210
// Transcoder claimed segments 0 through 3 twice
213211
await jobsManager.doubleClaimSegmentSlash(1, 0, 1, 0, {from: watcher})
214212

215-
// Transcoder claims again after it was slashed
216-
await jobsManager.claimWork(1, [0, 3], merkleTree.getHexRoot(), {from: transcoder2})
217-
// Wait through the verification period
218-
const verificationPeriod = await jobsManager.verificationPeriod.call()
219-
await roundsManager.mineBlocks(verificationPeriod.toNumber() + 1)
220-
// Make sure the round is initialized
221-
await roundsManager.initializeRound()
222-
223-
rand = web3.eth.getBlock(web3.eth.blockNumber).hash
224-
await roundsManager.setBlockHash(rand)
225-
// Watcher slashes transcoder for missing verification
226-
// transcoder should have submitted every segment for verification because the verification rate was 1 out of 1 segments
227-
await jobsManager.missedVerificationSlash(1, 2, 0, {from: watcher})
228-
229-
// Check that the transcoder is penalized twice (once for double claiming and once for missing verification)
230-
const currentRound = await roundsManager.currentRound()
231-
const doubleClaimSegmentSlashAmount = await jobsManager.doubleClaimSegmentSlashAmount.call()
232-
const missedVerificationSlashAmount = await jobsManager.missedVerificationSlashAmount.call()
233-
const penalty1 = Math.floor((1000 * doubleClaimSegmentSlashAmount.toNumber()) / 1000000)
234-
const transStakeRemaining1 = 1000 - penalty1
235-
const penalty2 = Math.floor((transStakeRemaining1 * missedVerificationSlashAmount.toNumber()) / 1000000)
236-
const expTransStakeRemaining = transStakeRemaining1 - penalty2
237-
const expDelegatedStakeRemaining = expTransStakeRemaining
238-
const expTotalBondedRemaining = expTransStakeRemaining
239-
const tokenEndSupply = await token.totalSupply.call()
240-
const watcherEndBalance = await token.balanceOf(watcher)
241-
const finderFeeAmount = await jobsManager.finderFee.call()
242-
const finderFee1 = Math.floor((penalty1 * finderFeeAmount) / 1000000)
243-
const finderFee2 = Math.floor((penalty2 * finderFeeAmount) / 1000000)
244-
const burned = tokenStartSupply.sub(tokenEndSupply).toNumber()
245-
const trans = await bondingManager.getDelegator(transcoder2)
246-
247-
assert.isNotOk(await bondingManager.isActiveTranscoder(transcoder2, currentRound), "transcoder should be inactive")
248-
assert.equal(await bondingManager.transcoderStatus(transcoder2), 0, "transcoder should not be registered")
249-
assert.equal(trans[0], expTransStakeRemaining, "wrong transcoder stake remaining")
250-
assert.equal(trans[3], expDelegatedStakeRemaining, "wrong delegated stake remaining")
251-
assert.equal(burned, (penalty1 + penalty2) - (finderFee1 + finderFee2), "wrong amount burned")
252-
253-
// Check that the finder was rewarded
254-
assert.equal(watcherEndBalance.sub(watcherStartBalance), finderFee1 + finderFee2, "wrong finder fee")
255-
256-
// Check that the broadcaster was refunded for both jobs
257-
assert.equal((await jobsManager.getJob(0))[8], 0, "job escrow should be 0")
258-
assert.equal((await jobsManager.getJob(1))[8], 0, "job escrow should be 0")
259-
assert.equal((await jobsManager.broadcasters.call(broadcaster))[0], 1000)
260-
261-
// Check that the total stake for the round is updated
262-
// activeTranscoderSet.call(round) only returns the active stake and not the array of transcoder addresses
263-
// because Solidity does not return nested arrays in structs
264-
assert.equal(await bondingManager.activeTranscoderSet.call(currentRound), 0, "wrong active stake remaining")
265-
266-
// Check that the total tokens bonded is updated
267-
assert.equal(await bondingManager.getTotalBonded(), expTotalBondedRemaining, "wrong total bonded amount")
213+
// Transcoder tries to submit another transcode claim to drain the broadcaster but fails
214+
// because it is no longer registered
215+
await expectThrow(jobsManager.claimWork(1, [0, 3], merkleTree.getHexRoot(), {from: transcoder2}))
268216
})
269217
})

0 commit comments

Comments
 (0)