5

I have attached my contract, which works fine on populus and compiles on geth. It is a simple source code: Test() function appends data into my linkedlist that is defined in my library. And get() function's goal is to retrieve the head nodes' data in byte32 format.

My goal is to pull head node's data(bytes32). Inside my contract I have this following functions Test() and get().

On populus; when I called Link Contract's get() function, I can see the value that is stored in Struct's data which is bytes32 type.

my_contract.transact().Test();
contract_address = unmigrated_chain.wait.for_receipt(set_txn_hash)
output = my_contract.call().get();
print(output[0] + output[1]);
abc111 //this is my output result. String that is stored in head node  
       //printed correctly.

On the other hand, on geth (by using my private Ethereum Blockchain), when I call get() function, instead of returning (bytes32,bytes32) value it returns its transaction address value.

ret_value = link.get({from: eth.accounts[0]})
"0xb508d62ce8c32d792cccf41f04f607d93c672e3a7e53e3e9fedb433ecc1f7a83"

[Q] On geth how could I get the nodes' data (like on populus as "abc111") value since on geth when I call get() function it returns transaction's address value instead of (bytes32, bytes32).

Note: Returning string might be a solution so also in library if I change data's type from "bytes32" with "string" type, I have faced with following error: Error: Return argument type inaccessible dynamic type is not implicitly convertible to expected type (type of first return variable) string memory.

Thank you for your valuable help and time.

The example code as follows from this original implementation (https://github.com/ethereum/dapp-bin/blob/master/library/linkedList.sol):

library LinkedList {
      struct data {
        uint80 head;
        uint80 last;
        uint80 count;
        Item[] items; 
      }
      uint80 constant None = uint80(0);
      struct Item {
        uint80 prev;
        uint80 next;
        bytes32 data;
        bytes32 data2; 
      }

  /// Appends `_data` to the end of the list self. Pushes the _data.
  function append(data storage self, bytes32 _data, bytes32 _data2) {
    var index = uint80(self.items.push(Item({prev: self.last, next: None, data: _data, data2: _data2})));
    if (self.last == None)
      {
    if (self.head != None || self.count != 0) throw;
    self.head = self.last = index;
    self.count = 1;
      }
    else
      {
    self.items[self.last - 1].next = index;
    self.last = index;
    self.count++;
      }
  }

  function get_head_data(data storage self) returns (bytes32,bytes32) {
    var it = iterate_start(self);
    return (iterate_get(self, it));
  }

  function get_head_iterate(data storage self) returns (uint80) {
    var it = iterate_start(self);    
    return it;
  }

  // Interface of Iterator
  function iterate_start(data storage self) returns (uint80) { return self.head; }
  function iterate_next(data storage self, uint80 _index) returns (uint80) { return self.items[_index - 1].next; }
  function iterate_get(data storage self, uint80 _index) returns (bytes32, bytes32) {
    return (self.items[_index - 1].data, self.items[_index - 1].data2); }
}

contract Link {
  using LinkedList for LinkedList.data;
  LinkedList.data public list;
  function Test() {
    list.append("abc","111");
    list.append("def", "222");
    list.append("ghf", "333");
  }

  function get() returns (bytes32, bytes32) {
    return (list.get_head_data());
  }
}
6

You want to use

link.call.get()

Also, a better way to do it is just to mark the get function constant. Then it will do a call by default.

This does a simulated transaction call and returns the value. Otherwise, you're doing an actual transaction, and getting the return value.

Dealing with strings can be tricky; they aren't value types, like bytes32, but are a pointer to a dynamic array of bytes, similar to char* in C. See the docs for more info

  • 1
    In general, you should avoid doing reads and writes in the same operation. If you feel you need to, you should use events – Tjaden Hess Oct 19 '16 at 20:10
  • 1
    ethereum.stackexchange.com/questions/765/… covers much of what you want to know with regards to transactions. – Tjaden Hess Oct 19 '16 at 20:12
  • 1
    The issue that you're facing with strings is that you can't pass dynamically sized memory objects between contracts, including libraries. What you can do is pass a storage pointer to a string to the library function, then modify the string at that address, since libraries share the same storage as the caller – Tjaden Hess Oct 19 '16 at 20:16
  • 1
    Also, the "no dynamically sized memory objects" statement isn't quite true, but that's a separate question. You can always come chat on gitter.im/ethereum/solidity – Tjaden Hess Oct 19 '16 at 20:18
  • 1
    Let us continue this discussion in chat. – Tjaden Hess Oct 19 '16 at 21:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.