-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
working anchor prototype #13
Conversation
…re acceptance of data
|
||
and then copy the `witness_contract.go` file to `centrifuge/witness/`. You will also need to modify the file to add the following imports: | ||
and then copy the `ethereum_anchor_registry_contract.go` file to `centrifuge/anchor/`. You will also need to modify the file to add the following imports: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just leave the go files in the contract repository and list them as dependencies here?
import "github.com/CentrifugeInc/centrifuge-ethereum-contracts/centrifuge/witness"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the contracts repo should hold the representation of all the possible client code. this should IMO be done by the implementing client instead.
or maybe by an intermediary project
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we planning on committing the ABI? That fits into the same category IMO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ABI is a bit in-between as it is somewhat native to the project. But eventually, I wouldn't commit the ABI either in the future. Just the code and then have a "release project" somewhere else to keep artifacts that are required for downstream projects.
watchOpts := &bind.WatchOpts{} | ||
watchOpts.Context = ethereum.DefaultWaitForTransactionMiningContext() | ||
|
||
sinkNo := make(chan *EthereumAnchorRegistryContractAnchorRegistered, 100) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does "sinkNo" mean?
@@ -38,59 +39,65 @@ func (ethRegistry *EthereumAnchorRegistry) RegisterAnchor(anchor *Anchor) (Ancho | |||
copy(bAnchorId[:], anchor.anchorID[:32]) | |||
var schemaVersion = big.NewInt(int64(anchor.schemaVersion)) | |||
|
|||
//listen to this particular anchor being mined/event is triggered |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really wait for it to be mined here? This could be an hour or more. Would we really want to rely on in channel memory for tracking which anchors still need to be mined? There could be quite a lot of these tx and restarting the process would lead to loosing all of them right?
|
||
and then copy the `witness_contract.go` file to `centrifuge/witness/`. You will also need to modify the file to add the following imports: | ||
and then copy the `ethereum_anchor_registry_contract.go` file to `centrifuge/anchor/`. You will also need to modify the file to add the following imports: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we planning on committing the ABI? That fits into the same category IMO.
package anchor | ||
|
||
type Anchor struct { | ||
AnchorID string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are you using a string here? An Anchor ID (and root hash) are not necessarily valid ascii strings. So representing those as a string doesn't give us any readable values unless we make the extra effort to encode them in base64 which is what we are doing when exposing them as in the REST api. I would not encode it in base64 as long as it doesn't need to be human readable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would make them all 32 char strings for upper level APIs. We don't really gain much from dealing just with bytes there and it is less intiutive in upstream APIs to deal with bytes (logging, debugging, etc).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But a 32 char string is not human readable either, because not every 8bit value is a valid ascii character in fact only 64 are human readable. You will end up with something that looks like garbage in your logs if you log a 256bit value converted to an ascii string (that's why people use base64 encoding). In the public api we already automatically convert a 256bit value to base64 strings and it's quite easy to make our logging do the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could have a custom byte type that just implements a different to string method that would print base64 encoding or you actually need to convert it to base64. I don't think it is a good idea, in many places (e.g. in libp2p) byte values are expected anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's an example that shows the issue of not converting to base64 and how we could still use raw byte values without actually using base64.
package main
import "encoding/base64"
import "fmt"
type base64Byte []byte
func (b base64Byte) String() string {
return base64.StdEncoding.EncodeToString(b)
}
func main() {
by := []byte{1,29, 200, 29, 210, 55, 102}
by64 := base64Byte(by)
fmt.Println("Raw bytes:", by)
fmt.Println("String of bytes:", string(by))
fmt.Println("Base64 byte:", by64)
}
// Output
Raw bytes: [1 29 200 29 210 55 102]
String of bytes: �����7f
Base64 byte: AR3IHdI3Zg==
package anchor | ||
|
||
import ( | ||
//"github.com/CentrifugeInc/go-centrifuge/centrifuge/ethereum" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clean up
} | ||
} | ||
|
||
func getAnchorContract() (anchorContract *EthereumAnchorRegistryContract, err error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Godoc style guide says that function descriptions should start with the full function name and be right outside the function. There are a few other spots as well where this is switched around.
Also it seems like it's not displaying anything :)
// getAnchorContract instantiates the contract and display its name
func getAnchorContract() (anchorContract *EthereumAnchorRegistryContract, err error) {
|
||
import ( | ||
"testing" | ||
"github.com/stretchr/testify/assert" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't used this library yet. (I did all my assertions manually) Did you put much thought into which "assertion" library we should use or did you just pick the first option you came across?
Might make sense to spend half an hour on looking at a few and then make a decision for one. I'd refactor my own code to use that library then. If you are saying that testify.assert is the best option, I'll go ahead and add it to my tests as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, it is the one I have seen used most often. We should use this to build up our testing framework for all our test cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For simple cases testify is good. However, I also created #24 to look into another framework that I found quite interesting when I did some research.
|
||
// Setting up the listened for the "AnchorRegistered" event to notify the upstream code about successful mining/creation | ||
// of the anchor. | ||
func setUpRegistrationEventListener(ethRegistryContract WatchAnchorRegistered, anchorToBeRegistered *Anchor, confirmations chan<- *Anchor) (err error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the asynch nature of this implementation, just a couple of comments:
- As we would have multiple types of ethereum "objects" would be good to try to abstract the event listener out of the anchoring domain. As we have an immediate use case with Identities, where we would like to have the same listener approach for any type. I would like to do that, as part of the identity work I am about to start.
- That being said, we will need to redesign this code anyways as we should be able to store pending requests so the flow works even if the node goes down.
As soon as we merge this in, I would refactor it to be a bit more abstract to process as well identities, or other types. In addition I will create a task to make this resilient to restarts.
scripts/test-ethereum/genesis.json
Outdated
"eip155Block": 0, | ||
"eip158Block": 0 | ||
}, | ||
"difficulty": "x200", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will this need to be "0x200" instead ?
I was trying to run the integration tests by running:
I have running the local geth by executing Tests fail waiting for the transaction to finish:
Any ideas, is there something off with my setup? When attaching to the ipc I see:
seems to be ok |
… mod: filter anchor registered event by "from" address
No description provided.