contract Library {
    // Notes:
    // - this is limited to a payload length of 253 bytes
    // - the payload should be ASCII as many clients will want to display this to the user
    function createBSMHash(string payload) pure internal returns (bytes32) {
        // \x18Bitcoin Signed Message:\n#{message.size.chr}#{message}
        string memory prefix = "\x18Bitcoin Signed Message:\n";
        return sha256(sha256(prefix, bytes1(bytes(payload).length), payload));
    }

    function validateBSM(string payload, address key, uint8 v, bytes32 r, bytes32 s) internal pure returns (bool) {
        return key == ecrecover(createBSMHash(payload), v, r, s);
    }
  
	//bytes32 constant mask4 = 0xffffffff00000000000000000000000000000000000000000000000000000000;
	//bytes1 constant network = 0x00;

    /*
	function getBitcoinAddress( bytes32 _xPoint, bytes32 _yPoint ) constant public returns( bytes20 hashedPubKey, bytes4 checkSum, bytes1 network)	{
		hashedPubKey 	= getHashedPublicKey(_xPoint, _yPoint);
 		checkSum 	= getCheckSum(hashedPubKey);
 		network 	= network;
	}*/

	function btcAddrPubKeyUncompr( bytes32 _xPoint, bytes32 _yPoint) internal pure returns( bytes20 hashedPubKey )	{
		bytes1 startingByte = 0x04;
 		return ripemd160(sha256(startingByte, _xPoint, _yPoint));
	}
	
	function btcAddrPubKeyCompr(bytes32 _x, bytes32 _y) internal pure returns( bytes20 hashedPubKey )	{
	    bytes1 _startingByte;
	    if (uint256(_y) % 2 == 0  ) {
            _startingByte = 0x02;
        } else {
            _startingByte = 0x03;
        }
 		return ripemd160(sha256(_startingByte, _x));
	}
	
	function ethAddressPublicKey( bytes32 _xPoint, bytes32 _yPoint) internal pure returns( address ethAddr )	{
 		return address(keccak256(_xPoint, _yPoint) ); 
	}
	/*
	function getCheckSum( bytes20 _hashedPubKey ) public pure returns(bytes4 checkSum) {
		var full = sha256((sha256(network, _hashedPubKey)));
		return bytes4(full&mask4);
	}
    */
    function toAsciiString(address x) internal pure returns (string) {
        bytes memory s = new bytes(42);
        s[0] = 0x30;
        s[1] = 0x78;
        for (uint i = 0; i < 20; i++) {
            byte b = byte(uint8(uint(x) / (2**(8*(19 - i)))));
            byte hi = byte(uint8(b) / 16);
            byte lo = byte(uint8(b) - 16 * uint8(hi));
            s[2+2*i] = char(hi);
            s[2+2*i+1] = char(lo);            
        }
        return string(s);
    }
    
    function char(byte b) internal pure returns (byte c) {
        if (b < 10) return byte(uint8(b) + 0x30);
        else return byte(uint8(b) + 0x57);
    }
    
    /*
    function getBTCAddr(bytes32 _xPoint, bytes32 _yPoint) pure public returns (bytes) {
		bytes20 hashedPubKey = btcAddressPublicKey(_xPoint, _yPoint);
		bytes4 checkSum = getCheckSum(hashedPubKey);
		bytes memory output = new bytes(25);
		
		output[0] = network[0];
		
		for (uint8 i = 0; i<20; i++) {
            output[i+1] = hashedPubKey[i];
        }
        
        for ( i = 0; i<4; i++) {
            output[i+1+20] = checkSum[i];
        }

        return output;
    }
    */
}
function toAsciiString(address x) internal pure returns (string) {
    bytes memory s = new bytes(42);
    s[0] = 0x30;
    s[1] = 0x78;
    for (uint i = 0; i < 20; i++) {
        byte b = byte(uint8(uint(x) / (2**(8*(19 - i)))));
        byte hi = byte(uint8(b) / 16);
        byte lo = byte(uint8(b) - 16 * uint8(hi));
        s[2+2*i] = char(hi);
        s[2+2*i+1] = char(lo);            
    }
    return string(s);
}

/*
 	function getCheckSum( bytes20 _hashedPubKey ) public pure returns(bytes4 checkSum) {
 		var full = sha256((sha256(network, _hashedPubKey)));
 		return bytes4(full&mask4);
 	}
 */