bitcoin-sv / sol2scrypt

Solidity to sCrypt Transplier
BSD 3-Clause "New" or "Revised" License
1 stars 0 forks source link

Simplify mapping #207

Closed xhliu closed 2 years ago

xhliu commented 2 years ago
contract Mapping {
    mapping(address => uint) public myMap;

    function get(address addr) external {
        myMap[addr]++;
    }

    function set(address addr, uint x) external {
        myMap[addr] = x;
    }
}

->

contract Mapping {
  @state
  public HashedMap<PubKeyHash, int> myMap;

  public function get(PubKeyHash addr, SigHashPreimage txPreimage, int this_myMap_addr, int this_myMap_addr_index) {
    require((!this.myMap.has(addr, this_myMap_addr_index) && this_myMap_addr == 0) || this.myMap.canGet(addr, this_myMap_addr, this_myMap_addr_index));
    this_myMap_addr++;
    require(this.myMap.set(addr, this_myMap_addr, this_myMap_addr_index));
    require(this.propagateState(txPreimage));
  }

  public function set(PubKeyHash addr, int x, SigHashPreimage txPreimage, int this_myMap_addr, int this_myMap_addr_index) {
    require((!this.myMap.has(addr, this_myMap_addr_index) && this_myMap_addr == 0) || this.myMap.canGet(addr, this_myMap_addr, this_myMap_addr_index));
    this_myMap_addr = x;
    require(this.myMap.set(addr, this_myMap_addr, this_myMap_addr_index));
    require(this.propagateState(txPreimage));
  }

  function propagateState(SigHashPreimage txPreimage) : bool {
    require(Tx.checkPreimage(txPreimage));
    bytes outputScript = this.getStateScript();
    bytes output = Utils.buildOutput(outputScript, SigHash.value(txPreimage));
    return hash256(output) == SigHash.hashOutputs(txPreimage);
  }
}

Let's refactor it to be more readable:

  1. this_myMap_addr -> myMap_addr
  2. this_myMap_addr_index -> i0
  3. preCheckMap & postCheckMap
  4. move SigHashPreimage txPreimage to always be the last arg

Now it looks cleaner. More obvious for more complex case of mapping.

contract Mapping {
  @state
  public HashedMap<PubKeyHash, int> myMap;

  public function get(PubKeyHash addr, int myMap_addr, int i0, SigHashPreimage txPreimage) {
    require(this.preCheckMap(addr, myMap_addr, i0));

    myMap_addr++;

    require(this.postCheckMap(addr, myMap_addr, i0));
    require(this.propagateState(txPreimage));
  }

  public function set(PubKeyHash addr, int x, int myMap_addr, int i0, SigHashPreimage txPreimage) {
    require(this.preCheckMap(addr, myMap_addr, i0));

    myMap_addr = x;

    require(this.postCheckMap(addr, myMap_addr, i0));
    require(this.propagateState(txPreimage));
  }

  function preCheckMap(PubKeyHash addr, int myMap_addr, int i) : bool {
    // 0 is the default value for its type: 0 for int here
    return (!this.myMap.has(addr, i) && myMap_addr == 0) || this.myMap.canGet(addr, myMap_addr, i);
  }

  function postCheckMap(PubKeyHash addr, int myMap_addr, int i) : bool {
    return this.myMap.set(addr, myMap_addr, i);
  }

  function propagateState(SigHashPreimage txPreimage) : bool {
    require(Tx.checkPreimage(txPreimage));
    bytes outputScript = this.getStateScript();
    bytes output = Utils.buildOutput(outputScript, SigHash.value(txPreimage));
    return hash256(output) == SigHash.hashOutputs(txPreimage);
  }
}