contract Ledger is Owned, SafeMath, Finalizable {
	Controller public controller;
	mapping(address => uint) public balanceOf;
	mapping (address => mapping (address => uint)) public allowance;
	uint public totalSupply;
	uint public mintingNonce;
	bool public mintingStopped;

	// functions below this line are onlyOwner

	function Ledger() {
	}

	function setController(address _controller) onlyOwner notFinalized {
		controller = Controller(_controller);
	}

	function stopMinting() onlyOwner {
		mintingStopped = true;
	}

	function multiMint(uint nonce, uint256[] bits) onlyOwner {
		require(!mintingStopped);
		if (nonce != mintingNonce) return;
		mintingNonce += 1;
		uint256 lomask = (1 << 96) - 1;
		uint created = 0;
		for (uint i=0; i<bits.length; i++) {
			address a = address(bits[i]>>96);
			uint value = bits[i]&lomask;
			balanceOf[a] = balanceOf[a] + value;
			controller.ledgerTransfer(0, a, value);
			created += value;
		}
		totalSupply += created;
	}

	// functions below this line are onlyController

	modifier onlyController() {
		require(msg.sender == address(controller));
		_;
	}

	function controllerMint(address to, uint amt) onlyController {
		require(!mintingStopped);
		balanceOf[to] = safeAdd(balanceOf[to], amt);
		totalSupply = safeAdd(totalSupply, amt);
	}

	function transfer(address _from, address _to, uint _value) onlyController returns (bool success) {
		if (balanceOf[_from] < _value) return false;

		balanceOf[_from] = safeSub(balanceOf[_from], _value);
		balanceOf[_to] = safeAdd(balanceOf[_to], _value);
		return true;
	}

	function transferFrom(address _spender, address _from, address _to, uint _value) onlyController returns (bool success) {
		if (balanceOf[_from] < _value) return false;

		var allowed = allowance[_from][_spender];
		if (allowed < _value) return false;

		balanceOf[_to] = safeAdd(balanceOf[_to], _value);
		balanceOf[_from] = safeSub(balanceOf[_from], _value);
		allowance[_from][_spender] = safeSub(allowed, _value);
		return true;
	}

	function approve(address _owner, address _spender, uint _value) onlyController returns (bool success) {
		// require user to set to zero before resetting to nonzero
		if ((_value != 0) && (allowance[_owner][_spender] != 0)) {
			return false;
		}

		allowance[_owner][_spender] = _value;
		return true;
	}

	function increaseApproval (address _owner, address _spender, uint _addedValue) onlyController returns (bool success) {
		uint oldValue = allowance[_owner][_spender];
		allowance[_owner][_spender] = safeAdd(oldValue, _addedValue);
		return true;
	}

	function decreaseApproval (address _owner, address _spender, uint _subtractedValue) onlyController returns (bool success) {
		uint oldValue = allowance[_owner][_spender];
		if (_subtractedValue > oldValue) {
			allowance[_owner][_spender] = 0;
		} else {
			allowance[_owner][_spender] = safeSub(oldValue, _subtractedValue);
		}
		return true;
	}

	function burn(address _owner, uint _amount) onlyController {
		balanceOf[_owner] = safeSub(balanceOf[_owner], _amount);
		totalSupply = safeSub(totalSupply, _amount);
	}
}
function Ledger() {
}

// functions below this line are onlyOwner