go-ethereum/bzz/bzzcontract/swarm.sol
2015-05-07 17:42:02 +02:00

124 lines
3.8 KiB
Solidity

/// @title Swarm Distributed Preimage Archive
/// @author Daniel A. Nagy <daniel@ethdev.com>
contract Swarm
{
uint constant GRACE = 50; // grace period for lost information in blocks
bytes32 constant MAGIC_NUMBER = "Swarm receipt";
struct Bee {
uint deposit; // amount deposited by this member
uint expiry; // expiration time of the deposit
bytes32 missing; // member accused of losing this swarm chunk
uint deadline; // block number before which chunk must be presented
}
mapping (address => Bee) swarm;
// block number of transactions presenting chunks
mapping (bytes32 => uint) presentedChunks;
function max(uint a, uint b) private returns (uint c) {
if(a >= b) return a;
return b;
}
/// @notice Sign up as a Swarm node for `time` seconds.
/// No term extension for nodes with non-clean status.
///
/// @dev Guards against term overflow and unauthorized extension,
/// but all funds are added to deposite irrespective of status.
///
/// @param time term of Swarm membership in seconds from now.
function signup(uint time) {
Bee b = swarm[tx.origin];
if(isClean(msg.sender) && now + time > now) {
b.expiry = max(b.expiry, now + time);
}
b.deposit += msg.value;
}
/// @notice Withdraw from Swarm, refund deposit.
///
/// @dev Only allowed with clean status and expired term.
function withdraw() {
Bee b = swarm[tx.origin];
if(now > b.expiry && isClean(msg.sender)) {
msg.sender.send(b.deposit);
b.deposit = 0;
}
}
/// @notice Total deposit for address `addr`.
/// No change in state.
///
/// @dev Not meaningful for "Guilty" status.
///
/// @param addr queried address.
///
/// @return balance of queried address.
function balance(address addr) returns (uint d) {
Bee b = swarm[addr];
return b.deposit;
}
/// @notice Determine clean status of address `addr`.
/// Changes the state, but only as a matter of optimization.
/// Works as accessor.
///
/// @dev Defined as no signed receipt has been presented for missing chunk.
///
/// @param addr queried address.
///
/// @return true if status is "Clean".
function isClean(address addr) returns (bool s) {
Bee b = swarm[addr];
if(b.missing != 0 && presentedChunks[b.missing] != 0) b.missing = 0;
return b.missing == 0; // nothing they signed is missing
}
/// @param suspect address of reported Swarm node
event Report(address suspect);
/// @notice Find out what is missing in case of a Report event.
///
/// @return 0 if nothing is missing, swarm hash otherwise
function whatIsMissing() returns (bytes32 h) {
bytes32 missing = swarm[tx.origin].missing;
if(presentedChunks[missing] != 0) missing = 0;
return missing;
}
/// @notice Report chunk `swarmHash` as missing.
///
/// @param swarmHash sha3 hash of the missing chunk
/// @param expiry expiration time of receipt
/// @param sig_v signature parameter v
/// @param sig_r signature parameter r
/// @param sig_s signature parameter s
function reportMissingChunk(bytes32 swarmHash, uint expiry,
uint8 sig_v, bytes32 sig_r, bytes32 sig_s) {
if(expiry < now) return;
bytes32 recptHash = sha3(MAGIC_NUMBER, swarmHash, expiry);
address signer = ecrecover(recptHash, sig_v, sig_r, sig_s);
if(!isClean(signer) || !expiresAfter(signer, now)) return;
Bee b = swarm[signer];
b.missing = swarmHash;
b.deadline = block.number + GRACE;
Report(signer);
}
/// @notice Determine if the deposit for `addr` is unaccessible until `time`.
/// No change in state.
///
/// @param addr queried address.
///
/// @param time queried time.
///
/// @return true if deposit expires after queried time.
function expiresAfter(address addr, uint time) returns (bool s) {
Bee b = swarm[addr];
return b.expiry > time;
}
}