...by Daniel Szego
quote
"On a long enough timeline we will all become Satoshi Nakamoto.."
Daniel Szego
Showing posts with label Pattern and Practices. Show all posts
Showing posts with label Pattern and Practices. Show all posts

Sunday, December 30, 2018

Solidity Tips and Tricks - struct at local function hack


Solidity has a lot of surprising and actually shitty characteristics. On thing is that a struct can be defined both in memory and in storage as well similarly to arrays. The problem is however that if you define your struct in a local function body, it overwrites the storage variables of the contract itself. On top unfortunately, if you create a struct in a function body without explicitly marking if it is a storage or a memory one, it is created automatically as a storage. So the following example:

contract StructHack {
    uint public myNum = 0;
    
    struct TestStruct {
        uint structNum;
    }
    
    function hackStruct() {
        TestStruct test;
        test.structNum = 22;
    }
}

Surprisingly, if you deploy the contract and call the function hackStruct, the myNum value will be initialized to 22.  

Wednesday, December 26, 2018

Solidity Tips and Tricks - transferring ether at fallback logic


There are basically three ways of sending ether from a solidity contract:

- contractAddress.call.value("sent_value")() is the less secure version of all of the possibilities. It opens the door for reentrancy and other attacks. It is usually not proposed to use this contract due to security reasons. However, if you transfer ether for a contract that has a complicated fallback functionality, actually this is the only possibility. If you want to fine-tune the gas price of the executed target logic, it is again the only possibility. 

- contractAddress.send("value") sends the value to the address in a way that only 23000 gas is allocated to a possible fallback logic. The call gives back a true or false value depending result of the logic. So it can not really be used at complicated fallback logic. 

- contractAddress.transfer("value") sends the value to the address in a way that only 23000 gas is allocated to a possible fallback logic. The call throws an exception if something goes wrong, so it is regarded as a more secure way of transferring values. It can not be used at complicated fallback logic either. 

Sunday, October 14, 2018

Fabric composer tips and tricks - item with ID already exist but not visible


Sometimes if you work with the Fabric Composer online playground and you create an item from a transaction you get the error message that the given id already exist even if it is not directly visible in the asset list. This is actually a "feature" of the online playground, it happens if the old item with the old id already existed but it was deleted. For some reasons it is sometimes cached somewhere that can not be explicitly deleted. What you can do in such situations that you redeploy the business network archive file:
- Make sure that the latest version of the .bna (business network archive) is downloaded.
- Delete the existing business network in the online playground.
- Rdeploy the business network from the downloaded .bna file.

Monday, October 8, 2018

Fabric composer tips and tricks - getting type of an asset


If you use inheritance of assets in fabric composer and want to implement a transaction that execution is dependent on the actual asset type, you can use the following convention. Supposing that you have inheriting assets, like:

asset Ancestor identified by assetId {
  o String assetId
}

asset Descendant extends Ancestor{
}

you can query the exact type and the namespace of the asset with the following code:

toState.$type
toState.$namespace


Tuesday, October 2, 2018

Fabric composer tips and tricks - call external web service


Integrating external data with a blockchain platform is sometimes pretty much tricky. One way of doing it is with an external service called Oraclize. As Oraclize has already an integration possibility with Hyperledger Fabric, it still does not have any integration possibilities with Fabric Composer. However, if you want to integrate a relative simple and external data, you can explicitly call an external service from the fabric composer like in the following example:

const webServiceInfo = await request.get({ uri:'https://webserviceurl', json: true});
const intParam = parseInt(webServiceInfo.ParameterInteger);

In the above example, we simply call a get a web service that delivers a json object that has property with the name ParameterInteger. More complicated scenarios can also be imagined, like post query, but generally the it is not proposed to put complex calculation into a smart contract. Another aspect which is important that the delivered result has to be static, otherwise the endorsement peers get different information, so they can not really produce valid RW sets, so no valid state can be reached.     

Friday, September 28, 2018

Fabric composer tips and tricks - revert transaction


Reverting a transaction is pretty easy in Hyperledger Fabric Composer, you just have to throw an error, like:

throw new Error('Error message');

If an error is thrown, the whole transaction is rolled back. However, surprisingly, the catch logic can be used to stop the exception propagation. If the exception is not propagated to the top, the transaction is not reverted.   

Fabric composer tips and tricks - auto increment id of an asset


Classical problem is at Hyperledger Fabric composer that one want to auto increment the id of a newly created asset or participant. On way of reaching it that we query at the creation process all the number of the already existing assets and we simple increase the id by one. The following code demonstrates an example code:

    const assetReg = await getAssetRegistry(namespace + '.Asset');   
    let existingAssets = await assetReg.getAll();
  
    let numberOfAssets = 0;
    await existingAssets .forEach(function (asset) {
      numberOfAssets ++;
    });

    let newAssetId =  numberOfAssets +1;

Certainly, the construct does not protect from "double spending": if two assets will be created in the same round, both might get the same id, so one will be discarded as invalid. One way can be to overcome the difficulties is to use beside the incremented asset id another input parameter of the asset, like the asset name. 



Wednesday, August 1, 2018

Solidity Pattern and Practices: CRUD (Create Read Update Delete) on asset


So let we imagine the situation that want to create some basic asset on the ethereum blockchain that mimics the CRUD (Create Read Update Delete) operations, possible considering different roles and rights as well for the different operations. We could use something similar. For the first run we can defined an enumeration giving the first set of basic access controls and some kind of an internal data structure that we want to modify:

contract CRUDAsset {

  enum RightsEnum{
      Create,
      Read,
      Update,
      Delete,
      Admin
  } 
  
  struct DataStruct {
      uint data;
  }

  DataStruct data;

As a second step we can define a possible right configuration for each address and give modifiers that check the existence of these modifiers and of course a constructor that gives admin right for the first account.  

  mapping(address => RightsEnum) rights;
  
  constructor(){
      rights[msg.sender] = RightsEnum.Admin;
  }
  
  modifier CanCreate {
      require(rights[msg.sender] == RightsEnum.Create);
      _;
  }
  
  modifier CanRead {
      require(rights[msg.sender] == RightsEnum.Read);
      _;
  }
  
  modifier CanUpdate {
      require(rights[msg.sender] == RightsEnum.Update);
      _;
  }

  modifier CanDelete {
      require(rights[msg.sender] == RightsEnum.Delete);
      _;
  }

  modifier IsAdmin {
      require(rights[msg.sender] == RightsEnum.Admin);
      _;
  }

After this step we can define the CRUD (Create, Read, Update, Delete) operations with the given access rights.  

  function Create(uint _initialData) CanCreate {
      data = DataStruct(_initialData);
  }

  function Read() CanRead returns (uint) {
      return data.data;
  }

  function Update(uint _newData) CanUpdate {
      data.data = _newData;
  }
  
  function Delete(uint _newData) CanDelete {
      data.data = 0;
  }

  function AddRight(address _to, uint _right) IsAdmin {
      rights[msg.sender] = RightsEnum(_right);
  }
}

Certainly, the structure can be refined in several ways: 
- It is not a general schema for any kind of a data, it is valid only for the one specified DataStruct structure. It is even difficult to extend it to general data structures as the basic elements has to be defined at the moment in the function signatures. 
- Read actually means only reading out from the contract or from the user interface. The variable is not secret if someone has direct access to a blockchain node. The situation can be fine-tuned with encryption or with zkSNARKs. 
- The model has the one address -> one access model. It can be extended on a long run to a one address - multiply access right version. 

Solidity Tips and Tricks - decentralized maintenance


In a blockchain system, you might sometimes have the problem, that there should some kind of a maintenance job that should be running regularly. For such a problems, you usually implement something as a maintenance or timer job in centralized systems. However considering a fully decentralized system it is pretty much unpractical. What might be a good direction is to create a special decentralized role for maintenance in a way that this role will be rewarded somehow for doing the maintenance. The idea is similar to the idea of the miners. A miner maintain the state of the blockchain and for that activity they are rewarded by the transaction fees and the newly generated coins. The idea can be repeated however, there might be further roles doing kind of a system maintenance jobs for a certain  monetary reward. A very simple solidity code for that can be seen in the followings:

contract DecentralizedOperation {
    mapping(address => uint) balanceOpReward;
    
    function Maintainance() {
        // do maintainance
        balanceOpReward[msg.sender]++;
    }
}

Tuesday, July 31, 2018

Solidity Tips and Tricks - running optimization


Let we imagine the situation that we have to implement a smart contract that needs to have some kind of an external optimization after every call of business logic, like optimizing an IOU graph. What we can do is to set a bool variable and two modifiers indicated if our data structure is optimized or not. If the data structure is optimized we can call any kind of a business logic. If it  is not optimized we should be able to call only the OptimizationLogic function. Certainly, access control rights and roles of such a system are pretty much questionable and need some more fine tuning. 

contract Optimization {
    bool optimized;
    
    constructor() {
        optimized = true;
    }
    
    modifier Optimized {
        require(optimized);
        _;
    }

    modifier NotOptimized {
        require(optimized == false);
        _;
    }
    
    function BusinessLogic() Optimized {
        // doing business business logic
        optimized = false;
    }

    function OptimizationLogic() NotOptimized {
        // doing optimization logic
        optimized = true;
    }
}

Simple IOU contract with optimization possibility on Ethereum

Simple systems administrating IUO contracts can be easily realized on the top of Ethereum. Let we say that accounts can issue new IOU-s that are administrated as credit and debit balance. Someone can issue an IOU to any particular account, but nobody can issue an IOU in the name of somebody else. There is a further external role for optimizing the IOU graph, for the first run optimizing only means reducing the difference of credit and debit balance for a certain node. The role can be at the moment anybody and for the activity there is an extra reward token as an incentive mechanism. A simple code is shown in the following example.

contract SimpleIOUWithOptimization {
    
 mapping(address => uint) creditBalances;
 mapping(address => uint) debitBalances;
 mapping(address => uint) rewardBalances;

    
 function issueCredit(address _to, uint _value) {
  creditBalances[msg.sender] += _value;
  creditBalances[_to] += _value;
    }
    
 function optimizeAccount(address _account){
  if((debitBalances[_account] - creditBalances[_account]) >= 0) {
   rewardBalances[msg.sender]+=  debitBalances[_account] -  
     creditBalances[_account];
   creditBalances[_account] = 0;
   debitBalances[_account] -= debitBalances[_account] -  
     creditBalances[_account]; 
  }
  else{
   rewardBalances[msg.sender] +=  creditBalances[_account] - 
     debitBalances[_account];
   debitBalances[_account] = 0;
   creditBalances[_account] -= creditBalances[_account] -
     debitBalances[_account]; 
  }
 }
}

Certainly in this use case, the optimization could be executed right at the credit issunance, however in more complicated scenarios this might be not the option. 

Friday, July 6, 2018

Solidity Tips and Tricks - modifier inheritance


In solidity modifiers are inherited and they always overwrite the modifier of the ancestor. There is no way to call the ancestor class modifier if it has been overwritten, however, you can reference both the ancestor and descendant elements as well in your modifier. As an example:

contract Ancestor {
    uint public number = 11;
    
    modifier IsBig  {
            require (number > 10);
            _;
    }
}

contract Descendant is Ancestor {
    uint public number = 22;

    modifier IsBig  {
            require (Ancestor.number < 20);
            _;
    }
    function testFv() IsBig {
        
    }
}

In testFv() there is no possible to reference on super.IsBig or Acesntor.IsBig, the only thing that you can call is the overwritten IsBig modifier. 

  

Thursday, July 5, 2018

Hashgraph SDK Tips and Tricks - implementing your first application


If you already started to implement your first application with the Hedera Hashgraph SDK as it was summarized in the previous blog, you should continue with the following:

1. Extend your State class with additional elements storing state variables, like lists, arrays, hashmaps.

2. Rewrite the copy functions of your State class to cover the newly introduced state variables. 

3. Implement custom query functions in the State class to query the newly introduced state variables. 

4. Rewrite the init function of the Main class, to use any kind of custom initialization. Like, you can query the setup up parameters of the config file with platform.getParameters(), or you can create new consoles or windows with the platform.createConsole(true) and platform.createWindow(true) functions.

5. Rewrite the run() function of the Main class to run any kind of the required custom logic for your node. 

Hashgraph SDK Tips and Tricks - starting with your first application


If you start with your first application with Hedera Hashgraph, the easiest way is to download the SDK from the homepage and copy and start modifying one of the existing applications. For this:

1. Download the project from : https://www.swirlds.com/download/

2. Copy one of the applications under  sdk/source

3. Rename the folder and rename the name references in the pom.xml file.

4. Open Eclipse

5. Import the files as a "Maven" project

6. Rename the Main and State java files, objects and all the references to the name of your projects

7. Press "Run As" as "Maven Install" to get the binaries. 

8. Configure your application in the config.txt file. 

9. Start and test your application with swirlds.


Hashgraph SDK Tips and Tricks - logging error


If you use the Hashgraph SDK demo applications for prototype development, you can recognize that debugging the applications is not so simple. What you can do is to start a separate console window, just for the errors and you can log every important ´piece of information or errors to this special console, like:

/** a console window for errors */
public Console errorconsole;
...
  public void init(Platform platform, long id) {
  ...
    this.errorconsole = platform.createConsole(true);
  ...
  }

  protected void LogException(Exception e) {
    errorconsole.out.println(e.toString()+" "+e.getMessage()+" ");
  }

  protected void LogMessage(String message) {
    errorconsole.out.println(message);
  }

Unfortunately, it does not work if you want to log from your state object. 

Sunday, June 17, 2018

Solidity Tips and Tricks - private variable value


Private variables from solidity are usually not so private as they are expected. Value of a private variable can be read out by someone running a full client node and having a javascript console. As an example, considering the following private variable of a contract:

contract PrivateContract {

    string private Password = "MyPassword123";

    constructor() public {
    }

By knowing the contract address and running a full node on the Ethereum network, you can easily read out the value of the private variable, like with:

 web3.eth.getStorageAt(contractAddress, 0)

which results the following hex value:

'0x4d7950617373776f72643132330000000000000000000000000000000000001a'

after encoding:

MyPassword123

So the message is simple, do not store private information in private variables on the blockchain, because it is not really private !


Wednesday, April 4, 2018

Solidity Tips and Tricks - difference between .call.value(), .send() and .transfer()


It is important to understand the difference of semantics and security implications of the different ways of sending ether to a contract:
- .call.value(ether) - sends ether to a contract by giving all the possible gas for the execution having a strong risk for reentrancy attacks. If it is succeeded true is returned if not false. 
- .send(ether) - sends ether to a contract by giving only 2300 gas for the execution making possible to do only logging and event and preventing reentrancy attacks. Similarly to the previous case if the call succeed it returns true, otherwise it returns false. 
- .transfer(ether) is tecnically the same as require(send(ether)), so if the ether sending not succeeding and error will be thrown and the transaction is reverted.  


Solidity security patterns - reentrancy


Reentrancy can happen if a smart contract calls a second one in a direct way or indirectly by transferring it ether. Typically at the code execution before the given statement terminates it called once again by another contract. Consider the following code fragments:

contract ReentrancyError {
  ...
  function withdraw(uint _amount) public{
    if(balances[msg.sender] >= _amount) {
      if(msg.sender.call.value(_amount)()) {
        balances[msg.sender] -= _amount;
      }
    }
  }
}

contract Attacker {

  function attack() public {
      target.withdraw(donated);
  }
  
  function() public payable{
      if (counter < 10) {
        counter++;
        target.withdraw(donated);
      }
  }
}

The withdraw function of the ReentrancyError contract is meant to be called by externally owned accounts, however a tricky hacker might force to call the function from a hacked contract. If so by calling the withdraw function at the msg.sender.call.value(_amount) by transferring ether to the Attacker contract the fallback function will be called, that calls the withdraw function back again. As balance of the sender is still not modified at this stage, the attacker will succeed to transfer the amount of ether once again starting a new cycle (up to 10).

Possible solutions in this example are:
- reducing the balance before the ether transfer
- using mutex
- using require statement instead of if

Solidity security patterns - difference between call delegate call and library call


It might be a little bit tricky to distinguish between the different kind of calls in solidity. Basically library call is realized on a low-level by delegate call and it is different from a standard call. In a standard call the context of the called contract is considered as active. In a library or delegate call the calling context, meaning variables, storage, visibility remain active. In other words in a library call only the function code of the called contract will be loaded, every other parameter remain the same. The situation can be best seen by the following contract examples: 

contract CalledContract {
    event showAddressEvent(address _from);
    function test() payable public {
        showAddressEvent(this);
    }
}

contract CallingContract {
    function callDifferentContracts(address _contractAddress) public {
        require(_contractAddress.call(bytes4(keccak256("test()"))));
        require(_contractAddress.delegatecall(bytes4(keccak256("test()"))));
        testLib.calledSomeLibFun();
    }
}

library testLib {
    event showAddressEvent(address _from);
    function calledSomeLibFun() public {
        showAddressEvent(this);
    }

By calling the callDifferentContracts function with the address of the CalledContract, the code first reveals the address of CalledContract as it is expected by a standard call. After that it shows the address of the CallingContract both at the delegatecall and at the library call examples. 

Solidity security patterns - delegatecall and callcode


The problem is both with delegatecall and callcode that they dynamically load the code of a smart contract and call its function. Hence they do this loading in a way that the context (storage, memory etc) of the calling contract is preserved. It means that from the called contract any kind of variables (even privates !) of the calling contract can be changed. So it must be particularly paid attention that only one specific smart contract and only one specific function is to be called by callcode or delegatecall.

contract TestCallCode {

  function callDelegateFunction(address _a, string _functionName)  {
        _a.delegatecall(bytes4(keccak256(_functionName)));
 }
}

In the previous example if an attacker can call the callDelegateFunction and influence the address, he can redirect the call to any smart contract of a choice and with the functionName any function can be called. Even if there is no direct match between the _a address and _functionName the system can be sometimes tricked like with implementing malicious code into the fallback function.