https://github.com/Sam16450/NAPS-EthNA
Tip revision: dfedc5518ef39345a5570efa624ac00edd96de96 authored by Sam16450 on 05 February 2021, 08:16:49 UTC
Update Simulation.R
Update Simulation.R
Tip revision: dfedc55
code.sol
pragma solidity >=0.4.24 <0.7.0;
pragma experimental ABIEncoderV2;
contract ethna{
address payable public sender; // The account sending payments.
address payable public recipient; // The account receiving the payments.
uint256 public expiration; // Timeout in case the recipient never closes.
uint[][] internal values; // Values in path
uint public value; // current balance of contract
address[][] internal addresses;
uint public maxProofSize; // arity
uint public maxPathLength;
uint id; // id of latest state
constructor (address payable _recipient, uint256 duration)
public
payable {
sender = msg.sender;
recipient = _recipient;
expiration = now + duration;
maxProofSize = 5;
maxPathLength = 5;
}
/// Recipient can close the channel at any time by presenting a
/// signed state and amount from the sender. The recipient will be sent that amount,
/// and the remainder will go back to the sender
function close(uint256 amount, bytes memory signature) public {
require(msg.sender == recipient);
require(isValidSignature(amount, signature));
recipient.transfer(amount);
selfdestruct(sender);
}
/// Part below is concerned only in case of disagreement between two parties
function add_state(uint idState, uint amount, bytes memory signature) public {
require(id<idState);
require(msg.sender == recipient);
require(isValidSignature(amount, signature));
id = idState;
value = amount;
}
/// Recipient sends most recent state signed by sender and valid ongoing
/// transactions, which are completed but not included in latest state
function addCompletedTransaction(
uint idTrans,
address[] memory _a,
uint[] memory _v,
address[] memory _pushPath,
uint[] memory _pushV,
bytes memory signature,
bytes memory signatureShort,
uint256 deadline,
uint k ///point in path where is channel
)
public payable
{
require(idTrans > id);
require(isValidPushSignature(idTrans, _pushPath, _pushV, signatureShort, _a[_a.length-1], deadline));
address finalRecipient = _a[maxPathLength-1];
require(isValidPathSignature(idTrans, _a, _v, finalRecipient, signature));///!!!????
///checking whether pushPath is proper:
for(uint j = 0; j < _pushPath.length; ++j){
require(_a[j] == _pushPath[j] && _v[j] <= _pushV[j]);
}
if (_a[k] == sender && _a[k+1] == recipient) {
value += _v[k];
id = idTrans;
}
}
/// recipient can present proof of cheating by Pn at k-th channel on path
function addCheatingProof(
uint idTrans,
address[] memory _a,
uint[] memory _v,
address[] memory _pushPath,
uint[] memory _pushV,
bytes[5] memory signatures,
bytes memory signatureShort,
uint256 deadline,
uint8 cheatPoint,
uint noPaths,
uint k
)
public payable
{
//address nonce = _a1[0]; ///nonce of transaction
require(idTrans>id);
uint vMax;
uint vPrev;
require(noPaths <= maxProofSize);
newTableAddress(_a, noPaths);
newTableInt(_v, noPaths);
address finalRecipient = _a[_a.length-1];/// setting finalRecipient
require(isValidPushSignature(idTrans, _pushPath, _pushV, signatureShort, finalRecipient, deadline));
for(uint i = 0; i < noPaths; ++i){
require(addresses[i][addresses[i].length-1] == finalRecipient); /// every path should end at the same addresses
require(isValidPathSignature(idTrans, addresses[i], values[i], finalRecipient, signatures[i]));
///checking whether pushPath is proper:
for(uint j = 0; j < _pushPath.length; ++j){
require(addresses[i][j] == _pushPath[j] && values[i][j] <= _pushV[j]);
if(values[i][cheatPoint] > vMax){vMax = values[i][cheatPoint];}
vPrev+= values[i][cheatPoint+1];
}
}
if (_a[_pushPath.length - 1] == sender && _a[_pushPath.length] == recipient) {
if(vMax < vPrev){
value += _pushV[k];
id = idTrans;
}
}
}
function closeDisagreement() public payable{
require(msg.sender == recipient);
recipient.transfer(value);
selfdestruct(sender);
}
/// if the timeout is reached without the recipient closing the channel,
/// then the Ether is released back to the sender.
function claimTimeout() public {
require(now >= expiration);
selfdestruct(sender);
}
/// core primitive used to validate signatures
function isValidSignature(uint256 amount, bytes memory signature)
internal
view
returns (bool)
{
bytes32 message = prefixed(keccak256(abi.encodePacked(this, amount)));
// check that the signature is from the payment sender
return recoverSigner(message, signature) == sender;
}
/// Validation of full path
function isValidPathSignature(uint _id, address[] memory a, uint[] memory v,
address finalRecipient, bytes memory signature)
internal
view
returns (bool)
{
require(a.length < maxPathLength);
bytes32 message = prefixed(keccak256(abi.encodePacked(this, _id, a, v)));
// check that signatures come from the payment sender
require(a[a.length-1] == finalRecipient);
return recoverSigner(message, signature) == finalRecipient;
}
/// Validation of short path
function isValidPushSignature(
uint _id,
address[] memory a,
uint[] memory v,
bytes memory signature,
address finalRecipient,
uint256 deadline
)
internal
view
returns (bool)
{
require(deadline < now);
require(a[a.length-3] == sender);
bytes32 message = prefixed(keccak256(abi.encodePacked(this, _id, a, v, finalRecipient)));
// check that the signature is from the payment sender
return recoverSigner(message, signature) == sender;
}
//internal functions
function newTableAddress(address[] memory _a, uint no_paths
) internal
{
for(uint i = 0; i < no_paths; ++i){
addresses.push([_a[2*i], _a[2*i+1], _a[2*i+2], _a[2*i+3], _a[2*i+4]
]);
}
}
function newTableInt(uint[] memory _v, uint no_paths
) internal
{
for(uint i = 0; i < no_paths; ++i){
values.push([_v[2*i], _v[2*i+1],_v[2*i+2], _v[2*i+3],_v[2*i+4]
]);
}
}
/// core primitive
function splitSignature(bytes memory sig)
internal
pure
returns (uint8 v, bytes32 r, bytes32 s)
{
require(sig.length == 65);
assembly {
// first 32 bytes, after the length prefix
r := mload(add(sig, 32))
// second 32 bytes
s := mload(add(sig, 64))
// final byte (first byte of the next 32 bytes)
v := byte(0, mload(add(sig, 96)))
}
return (v, r, s);
}
function recoverSigner(bytes32 message, bytes memory sig)
internal
pure
returns (address)
{
(uint8 v, bytes32 r, bytes32 s) = splitSignature(sig);
return ecrecover(message, v, r, s);
}
/// build a prefixed hash to mimic the behavior of eth_sign.
function prefixed(bytes32 hash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
}